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/m2ua/m2ua_spp.c


File /code/strss7/drivers/m2ua/m2ua_spp.c



#ident "@(#) $RCSfile: m2ua_spp.c,v $ $Name:  $($Revision: 0.8.2.2 $) $Date: 2003/04/03 19:50:20 $"

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

#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 "../../include/ss7/sl.h"
#include "../sl/sl_prov.h"

#include "../ua/ua_data.h"
#include "m2ua_data.h"
#include "../ua/ua_msg.h"
#include "m2ua_msg.h"
#include "../ua/ua_asp.h"

/*
 *  =========================================================================
 *
 *  M2UA Peer --> M2UA (SPP) Received messages
 *
 *  =========================================================================
 *  This file processes M2UA messages recevied at an SPP (IPSP).  SPP messages
 *  are passed upwards to an ASP interface.  M2UA doesn't really have a
 *  peer-to-peer interface specified, but it might be possible.  This could
 *  replace M2PA functionality.  We give it a shot here.
 */

/*
 *  MAUP DATA (SG-->AS or AS-->SG) (Pass along as M_DATA)
 *  -------------------------------------------------------------------------
 */
static int m2ua_recv_data(spp_t * spp, mblk_t * msg)
{
	uint32_t tag, *p = ((uint32_t *) msg->b_rptr) + 4;
	size_t len = UA_SIZE(*p);
	tag = *p++ & UA_TAG_MASK;
	/* 
	 *  FIXME: We also need to look for a Correlation Id in the message
	 *  and use it to reset the MSU correlation number if there is an Id
	 *  in the message.
	 *
	 *  Note also that every data message should be acknowledged once the
	 *  message has been passed to Level 3.
	 */
	if (tag != M2UA_PARM_DATA1 && tag != M2UA_PARM_DATA2)
		return -EPROTO;
	if (len > msg->b_wptr - (unsigned char *) p)
		return -EMSGSIZE;
	msg->b_datap->db_type = M_DATA;
	msg->b_rptr = (unsigned char *) p;
	msg->b_wptr = (unsigned char *) p + len;
	putq(q, msg);
	return (0);
}

/*
 *  MAUP ESTABLISH REQUEST (AS-->SG) (Pass along as M_PROTO)
 *  -------------------------------------------------------------------------
 */
static int m2ua_recv_estab_req(spp_t * spp, mblk_t * msg)
{
	(void) q;
	(void) msg;
	return (-EOPNOTSUPP);
}

/*
 *  MAUP ESTABLISH CONFIRM (SG-->AS) (Pass along as M_PROTO)
 *  -------------------------------------------------------------------------
 */
static int m2ua_recv_estab_con(spp_t * spp, mblk_t * msg)
{
	(void) q;
	(void) msg;
	return (-EOPNOTSUPP);
}

/*
 *  MAUP RELEASE REQUEST (AS-->SG) (Pass along as M_PROTO)
 *  -------------------------------------------------------------------------
 */
static int m2ua_recv_rel_req(spp_t * spp, mblk_t * msg)
{
	(void) q;
	(void) msg;
	return (-EOPNOTSUPP);
}

/*
 *  MAUP RELEASE CONFIRM (SG-->AS) (Pass along as M_PROTO)
 *  -------------------------------------------------------------------------
 */
static int m2ua_recv_rel_con(spp_t * spp, mblk_t * msg)
{
	(void) q;
	(void) msg;
	return (-EOPNOTSUPP);
}

/*
 *  MAUP RELEASE INDICATION (SG-->AS) (Pass along as M_PROTO)
 *  -------------------------------------------------------------------------
 */
static int m2ua_recv_rel_ind(spp_t * spp, mblk_t * msg)
{
	(void) q;
	(void) msg;
	return (-EOPNOTSUPP);
}

/*
 *  MAUP STATE REQUEST (AS-->SG) (Pass along as M_PROTO)
 *  -------------------------------------------------------------------------
 */
static int m2ua_recv_state_req(spp_t * spp, mblk_t * msg)
{
	uint32_t *p = ((uint32_t *) msg->b_rptr) + 4;
	union SL_primitives *m = (union SL_primitives *) msg->b_rptr;
	if (*p++ != M2UA_PARM_STATE_REQUEST)
		return -EPROTO;
	switch (*p++) {
	case M2UA_STATUS_LPO_SET:
		m->sl_primitive = SL_LOCAL_PROCESSOR_OUTAGE_REQ;
		break;
	case M2UA_STATUS_LPO_CLEAR:
		m->sl_primitive = SL_RESUME_REQ;
		break;
	case M2UA_STATUS_EMER_SET:
		m->sl_primitive = SL_EMERGENCY_REQ;
		break;
	case M2UA_STATUS_EMER_CLEAR:
		m->sl_primitive = SL_EMERGENCY_CEASES_REQ;
		break;
	case M2UA_STATUS_FLUSH_BUFFERS:
		m->sl_primitive = SL_CLEAR_BUFFERS_REQ;
		break;
	case M2UA_STATUS_CONTINUE:
		m->sl_primitive = SL_RESUME_REQ;
		break;
	case M2UA_STATUS_AUDIT:
		/* 
		 *  FIXME: return state according to 5.3.8
		 */
		freemsg(msg);
		return (0);
	case M2UA_STATUS_CONG_CLEAR:
		m->sl_primitive = SL_NO_CONGESTION_REQ;
		break;
	case M2UA_STATUS_CONG_ACCEPT:
		m->sl_primitive = SL_CONGESTION_ACCEPT_REQ;
		break;
	case M2UA_STATUS_CONG_DISCARD:
		m->sl_primitive = SL_CONGESTION_DISCARD_REQ;
		break;
	default:
		return (-EPROTO);
	}
	msg->b_datap->db_type = M_PROTO;
	msg->b_band = 2;	/* expedite around data */
	msg->b_wptr = msg->b_rptr + sizeof(m->sl_primitive);
	putq(q, msg);
	return (0);
}

/*
 *  MAUP STATE CONFIRM
 *  -------------------------------------------------------------------------
 */
static int m2ua_recv_state_con(spp_t * spp, mblk_t * msg)
{
	uint32_t *p = ((uint32_t *) msg->b_rptr) + 4;
	sl_t *sl = Q_SL(q);
	if (*p++ != M2UA_PARM_STATE_REQUEST)
		return -EPROTO;
	switch (*p++) {
	case M2UA_STATUS_LPO_SET:
		sl->pflags &= ~S_PF_LPO_SET;
		break;
	case M2UA_STATUS_LPO_CLEAR:
		sl->pflags &= ~S_PF_LPO_CLEAR;
		break;
	case M2UA_STATUS_EMER_SET:
		sl->pflags &= ~S_PF_EMER_SET;
		break;
	case M2UA_STATUS_EMER_CLEAR:
		sl->pflags &= ~S_PF_EMER_CLEAR;
		break;
	case M2UA_STATUS_FLUSH_BUFFERS:
		sl->pflags &= ~S_PF_FLUSH_BUFFERS;
		break;
	case M2UA_STATUS_CONTINUE:
		sl->pflags &= ~S_PF_CONTINUE;
		break;
	case M2UA_STATUS_AUDIT:
		sl->pflags &= ~S_PF_AUDIT;
		break;
	case M2UA_STATUS_CONG_CLEAR:
		sl->pflags &= ~S_PF_CONG_CLEAR;
		break;
	case M2UA_STATUS_CONG_ACCEPT:
		sl->pflags &= ~S_PF_CONG_ACCEPT;
		break;
	case M2UA_STATUS_CONG_DISCARD:
		sl->pflags &= ~S_PF_CONG_DISCARD;
		break;
	default:
		return (-EPROTO);
	}
	if (!sl->pflags)
		untimeout(xchg(&sl->resp_timer, 0));
	freemsg(msg);
	return (0);
}

/*
 *  MAUP STATE INDICATION
 *  -------------------------------------------------------------------------
 */
static int m2ua_recv_state_ind(spp_t * spp, mblk_t * msg)
{
	uint32_t *p = ((uint32_t *) msg->b_wptr) + 4;
	union SL_primitives *m = (union SL_primitives *) msg->b_rptr;
	if (*p++ != M2UA_PARM_STATE_EVENT)
		return -EPROTO;
	switch (*p++) {
	case M2UA_EVENT_RPO_ENTER:
		m->sl_primitive = SL_REMOTE_PROCESSOR_OUTAGE_IND;
		break;
	case M2UA_EVENT_RPO_EXIT:
		m->sl_primitive = SL_REMOTE_PROCESSOR_RECOVERED_IND;
		break;
	default:
	case M2UA_EVENT_LPO_ENTER:
	case M2UA_EVENT_LPO_EXIT:
		return (-EPROTO);
	}
	msg->b_datap->db_type = M_PROTO;
	msg->b_band = 2;	/* expedite around data */
	msg->b_wptr = msg->b_rptr + sizeof(m->sl_primitive);
	putq(q, msg);
	return (0);
}

/*
 *  MAUP RETRIEVAL REQUEST
 *  -------------------------------------------------------------------------
 */
static int m2ua_recv_retr_req(spp_t * spp, mblk_t * msg)
{
	uint32_t *p = ((uint32_t *) msg->b_wptr) + 4;
	union SL_primitives *m = (union SL_primitives *) msg->b_rptr;
	ulong fsnc;
	if (msg->b_wptr - msg->b_rptr < 6 * sizeof(*p))
		return -EMSGSIZE;
	if (*p++ != M2UA_PARM_ACTION)
		return -EPROTO;
	switch (*p++) {
	case M2UA_ACTION_RTRV_BSN:
		m->sl_primitive = SL_RETRIEVE_BSNT_REQ;
		msg->b_wptr = msg->b_rptr + sizeof(m->sl_primitive);
		break;
	case M2UA_ACTION_RTRV_MSGS:
		if (msg->b_wptr - msg->b_rptr < 8 * sizeof(*p))
			return -EMSGSIZE;
		if (*p++ != M2UA_PARM_SEQNO)
			return -EPROTO;
		fsnc = ntohl(*p++);
		m->sl_primitive = SL_RETRIEVAL_REQUEST_AND_FSNC_REQ;
		m->retrieval_request_and_fsnc_req.sl_fsnc = fsnc;
		msg->b_wptr = msg->b_rptr + sizeof(m->retrieval_request_and_fsnc_req);
		break;
	case M2UA_ACTION_DROP_MSGS:
		m->sl_primitive = SL_CLEAR_RTB_REQ;
		msg->b_wptr = msg->b_rptr + sizeof(m->sl_primitive);
		break;
	case M2UA_ACTION_RTRV_TRANS:
		return -EPROTO;
	default:
		return -EPROTO;
	}
	msg->b_datap->db_type = M_PROTO;
	msg->b_band = 2;	/* expedite around data */
	putq(q, msg);
	return (0);
}

/*
 *  MAUP RETRIEVAL CONFIRM
 *  -------------------------------------------------------------------------
 */
static int m2ua_recv_retr_con(spp_t * spp, mblk_t * msg)
{
	uint32_t *p = ((uint32_t *) msg->b_wptr) + 4;
	union SL_primitives *m = (union SL_primitives *) msg->b_rptr;
	(void) p;
	(void) m;
	return (-EOPNOTSUPP);
}

/*
 *  MAUP RETRIEVAL INDICATION
 *  -------------------------------------------------------------------------
 */
static int m2ua_recv_retr_ind(spp_t * spp, mblk_t * msg)
{
	uint32_t *p = ((uint32_t *) msg->b_wptr) + 4;
	union SL_primitives *m = (union SL_primitives *) msg->b_rptr;
	(void) p;
	(void) m;
	return (-EOPNOTSUPP);
}

/*
 *  MAUP RETRIEVAL COMPLETE INDICATION
 *  -------------------------------------------------------------------------
 */
static int m2ua_recv_retr_comp_ind(spp_t * spp, mblk_t * msg)
{
	uint32_t *p = ((uint32_t *) msg->b_wptr) + 4;
	union SL_primitives *m = (union SL_primitives *) msg->b_rptr;
	(void) p;
	(void) m;
	return (-EOPNOTSUPP);
}

/*
 *  MAUP CONGESTION INDICATION
 *  -------------------------------------------------------------------------
 */
static int m2ua_recv_cong_ind(spp_t * spp, mblk_t * msg)
{
	uint32_t *p = ((uint32_t *) msg->b_wptr) + 4;
	union SL_primitives *m = (union SL_primitives *) msg->b_rptr;
	ulong cong, disc;
	if (msg->b_wptr - msg->b_rptr < 8 * sizeof(*p))
		return -EMSGSIZE;
	if (*p++ != M2UA_PARM_CONG_STATUS)
		return -EPROTO;
	switch ((cong = *p++)) {
	case M2UA_LEVEL_NONE:
	case M2UA_LEVEL_1:
	case M2UA_LEVEL_2:
	case M2UA_LEVEL_3:
		break;
	case M2UA_LEVEL_4:
		/* TODO: tell sender to go away! */
	default:
		return -EPROTO;
	}
	if (*p++ != M2UA_PARM_DISC_STATUS)
		return -EPROTO;
	switch ((disc = *p++)) {
	case M2UA_LEVEL_NONE:
	case M2UA_LEVEL_1:
	case M2UA_LEVEL_2:
	case M2UA_LEVEL_3:
		break;
	case M2UA_LEVEL_4:
		/* TODO: tell sender to go away! */
	default:
		return -EPROTO;
	}
	m->link_congested_ind.sl_primitive = SL_LINK_CONGESTED_IND;
	m->link_congested_ind.sl_cong_status = ntohl(cong);
	m->link_congested_ind.sl_disc_status = ntohl(disc);
	msg->b_datap->db_type = M_PROTO;
	msg->b_band = 2;	/* expedite around data */
	msg->b_wptr = msg->b_rptr + sizeof(m->link_congested_ind);
	putq(q, msg);
	return (0);
}

/*
 *  MAUP DATA ACK (SG-->AS or AS-->SG)
 *  -------------------------------------------------------------------------
 */
static int m2ua_recv_data_ack(spp_t * spp, mblk_t * msg)
{
	uint32_t tag, *p = ((uint32_t *) msg->b_rptr) + 4;
	size_t len = UA_SIZE(*p);
	tag = *p++ & UA_TAG_MASK;
	if (tag != M2UA_PARM_CORR_ID_ACK)
		return -EPROTO;
	if (len > msg->b_wptr - (unsigned char *) p)
		return -EMSGSIZE;
	/* 
	 *  FIXME:  Ok, so now we have a data ack, what do we do with it?  We
	 *  must somehow adjust the SL implementation to only acknowledge data
	 *  which has been successfully delivered upstream.  Then we need to
	 *  disable the SL read queue when an acknowledgement is pending and
	 *  enable it when data is received.  We can set the flow control
	 *  thresholds on the queue to have a high water mark of 1 byte to
	 *  ensure that only one message is in the read queue at a given point
	 *  in time.
	 */
	freemsg(msg);
	return (0);
}

/*
 *  UA_RKMM_REG_REQ
 *  -------------------------------------------------------------------------
 */
static int m2ua_recv_reg_req(spp_t * spp, mblk_t * msg)
{
	(void) q;
	(void) msg;
	return (-EFAULT);
}

/*
 *  UA_RKMM_REG_RSP
 *  -------------------------------------------------------------------------
 */
static int m2ua_recv_reg_rsp(spp_t * spp, mblk_t * msg)
{
	(void) q;
	(void) msg;
	return (-EFAULT);
}

/*
 *  UA_RKMM_DEREG_REQ
 *  -------------------------------------------------------------------------
 */
static int m2ua_recv_dereg_req(spp_t * spp, mblk_t * msg)
{
	(void) q;
	(void) msg;
	return (-EFAULT);
}

/*
 *  UA_RKMM_DEREG_RSP
 *  -------------------------------------------------------------------------
 */
static int m2ua_recv_dereg_rsp(spp_t * spp, mblk_t * msg)
{
	(void) q;
	(void) msg;
	return (-EFAULT);
}

/*
 *  Common defined ASP/SGP management procedures.
 */
extern int (*ua_spp_mgmt[]) (spp_t *, mblk_t *);
extern int (*ua_spp_asps[]) (spp_t *, mblk_t *);
extern int (*ua_spp_aspt[]) (spp_t *, mblk_t *);

static int (*m2ua_maup[]) (spp_t *, mblk_t *) = {
	NULL,			/* (reserved) 0x0 */
	    m2ua_recv_data,	/* M2UA_MAUP_DATA 0x1 */
	    m2ua_recv_estab_req,	/* M2UA_MAUP_ESTAB_REQ 0x2 */
	    m2ua_recv_estab_con,	/* M2UA_MAUP_ESTAB_CON 0x3 */
	    m2ua_recv_rel_req,	/* M2UA_MAUP_REL_REQ 0x4 */
	    m2ua_recv_rel_con,	/* M2UA_MAUP_REL_CON 0x5 */
	    m2ua_recv_rel_ind,	/* M2UA_MAUP_REL_IND 0x6 */
	    m2ua_recv_state_req,	/* M2UA_MAUP_STATE_REQ 0x7 */
	    m2ua_recv_state_con,	/* M2UA_MAUP_STATE_CON 0x8 */
	    m2ua_recv_state_ind,	/* M2UA_MAUP_STATE_IND 0x9 */
	    m2ua_recv_retr_req,	/* M2UA_MAUP_RETR_REQ 0xa */
	    m2ua_recv_retr_con,	/* M2UA_MAUP_RETR_CON 0xb */
	    m2ua_recv_retr_ind,	/* M2UA_MAUP_RETR_IND 0xc */
	    m2ua_recv_retr_comp_ind,	/* M2UA_MAUP_RETR_COMP_IND 0xd */
	    m2ua_recv_cong_ind,	/* M2UA_MAUP_CONG_IND 0xe */
	    m2ua_recv_data_ack	/* M2UA_MAUP_DATA_ACK 0xf */
};
static int (*m2ua_rkmm[]) (spp_t *, mblk_t *) = {
	NULL,			/* (reserved) 0x0 */
	    m2ua_recv_reg_req,	/* UA_RKMM_REG_REQ 0x1 */
	    m2ua_recv_reg_rsp,	/* UA_RKMM_REG_RSP 0x2 */
	    m2ua_recv_dereg_req,	/* UA_RKMM_DEREG_REQ 0x3 */
	    m2ua_recv_dereg_rsp	/* UA_RKMM_DEREG_RSP 0x4 */
};

static struct msg_class msg_decode[] = {
	{ua_spp_mgmt, UA_MGMT_LAST},	/* UA_CLASS_MGMT 0x0 */
	{NULL, 0},		/* UA_CLASS_XFER 0x1 */
	{NULL, 0},		/* UA_CLASS_SNMM 0x2 */
	{ua_spp_asps, UA_ASPS_LAST},	/* UA_CLASS_ASPS 0x3 */
	{ua_spp_aspt, UA_ASPT_LAST},	/* UA_CLASS_ASPT 0x4 */
	{NULL, 0},		/* UA_CLASS_Q921 0x5 */
	{m2ua_maup, M2UA_MAUP_LAST},	/* UA_CLASS_MAUP 0x6 */
	{NULL, 0},		/* UA_CLASS_CNLS 0x7 */
	{NULL, 0},		/* UA_CLASS_CONS 0x8 */
	{m2ua_rkmm, UA_RKMM_LAST},	/* UA_CLASS_RKMM 0x9 */
	{NULL, 0},		/* UA_CLASS_TDHM 0xa */
	{NULL, 0}		/* UA_CLASS_TCHM 0xb */
};

int m2ua_spp_recv_msg(spp_t * spp, mblk_t * msg)
{
	return ua_recv_msg(q, msg, msg_decode);
}


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

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

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