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


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



#ident "@(#) $RCSfile: m2ua_sl.c,v $ $Name:  $($Revision: 0.8.2.1 $) $Date: 2002/10/18 03:28:38 $"

static char const ident[] =
    "$RCSfile: m2ua_sl.c,v $ $Name:  $($Revision: 0.8.2.1 $) $Date: 2002/10/18 03:28:38 $";

/*
 *  =========================================================================
 *
 *  SLP --> M2UA (SGP) Upstream Primitive
 *
 *  =========================================================================
 *
 *  These primitives are sent from the lower mux Signalling Link in SG
 *  operation to a Signalling Gateware Process.
 */

/*
 *  SL_INFO_ACK
 *  -------------------------------------------------------------------------
 *  The SGP has sent an SL_INFO_REQ and have received an acknowledgement.
 *  The INFO_REQ is used by the SGP to obtain information about the signalling
 *  link STREAM which may be pertinent to Signalling Gateway operation.
 */
static int sl_info_ack(queue_t * q, mblk_t * mp)
{
	slp_t *sl = ((sl_t *) q->q_ptr)->iid;
	sl_info_ack_t *p = (sl_info_ack_t *) mp->b_rptr;
	if (mp->b_wptr - mp->b_rptr < sizeof(*p))
		return -EPROTO;
	sl->version = p->sl_version;
	sl->state = p->sl_state;
	sl->max_sdu = p->sl_max_sdu;
	sl->min_sdu = p->sl_min_sdu;
	sl->header_len = p->sl_header_len;
	sl->ppa_style = p->sl_ppa_style;
	mp->b_rptr += sizeof(*p);
	bcopy(mp->b_rptr, sl->ppa, mp->b_wptr - mp->b_rptr);
	freemsg(mp);
	return (0);
}

/*
 *  SL_OK_ACK
 *  -------------------------------------------------------------------------
 */
static int sl_ok_ack(queue_t * q, mblk_t * mp)
{
	slp_t *sl = ((slp_t *) q->q_ptr)->iid;
	sl_ok_ack_t *p = (sl_ok_ack_t *) mp->b_rptr;
	if (mp->b_wptr - mp->b_rptr < sizeof(*p))
		return -EPROTO;
	switch (p->sl_correct_primitive) {
	case SL_ATTACH_REQ:
		sl->state = SL_DISABLED;
		/* 
		 *  An attach is peformed when a registration attempt is made
		 *  against a routing key.  M2UA does not have registrations
		 *  (yet) but I will propose them to sigtran.  We should
		 *  respond to the registering ASP with a REG RSP indicating
		 *  successful registration against the Link Key (SDTI/SDLI)
		 *  and provide it with a Interface Identifier.  The Interface
		 *  Identifier should be the SGP Id (our process) SDTI/SDLI
		 *  concatenated into a 32-bit integer guaranteeing that the
		 *  Interface Identifier is unique across the SG.
		 */
		m2ua_sl_attached(sl);
		freemsg(mp);
		return (0);

	case SL_DETACH_REQ:
		sl->state = SL_UNATTACHED;
		/* 
		 *  A detach is performed under some circumstances when a
		 *  deregistration request results in the last ASP associated
		 *  with a Link Key deregistering.  No response is pending
		 *  here, because we have already sent a DREG RSP.  We can
		 *  just mark the stream a unattached and leave it in it's
		 *  pool.
		 */
		m2ua_sl_detached(sl);
		freemsg(mp);
		return (0);
	}
	return -EPROTO;
}

/*
 *  SL_ERROR_ACK
 *  -------------------------------------------------------------------------
 */
static int sl_error_ack(queue_t * q, mblk_t * mp)
{
	int err;
	slp_t *sl = ((sl_t *) q->q_ptr)->iid;
	sl_error_ack_t *p = (sl_error_ack_t *) mp->b_rptr;
	if (mp->b_wptr - mp->b_rptr < sizeof(*p))
		return -EPROTO;
	if ((err = p->sl_errno) == SL_SYSERR)
		err = -p->sl_reason;
	switch (p->sl_error_primitive) {
		return -EFAULT;
	case SL_ATTACH_REQ:
		sl->state = SL_UNATTACHED;
		if ((err = m2ua_sl_attach_failed(sl, err)))
			return (err);
		break;
	case SL_DETACH_REQ:
		sl->state = SL_DISABLED;
		if ((err = m2ua_sl_detach_failed(sl, err)))
			return (err);
		break;
	case SL_ENABLE_REQ:
		sl->state = SL_DISABLED;
		if ((err = m2ua_sl_enable_failed(sl, err)))
			return (err);
		break;
	case SL_DISABLE_REQ:
		sl->state = SL_ENABLED;
		if ((err = m2ua_sl_disable_failed(sl, err)))
			return (err);
		break;

	case SL_INFO_REQ:
	case SL_OPTMGMT_REQ:
	case SL_NOTIFY_REQ:
		/* 
		 *  We actually want to notify management in these cases of a
		 *  pontential software error?
		 */
		return -EFAULT;
	default:
		/* 
		 *  We should notify manageent of a software error, perhaps do
		 *  an M_ERROR on the stream and move it to the SL_UNSUABLE
		 *  state.
		 */
		return -EPROTO;
	}
	freemsg(mp);
	return (0);
}

/*
 *  SL_ENABLE_CON
 *  -------------------------------------------------------------------------
 */
static int sl_enable_con(queue_t * q, mblk_t * mp)
{
	int err;
	slp_t *sl = ((sl_t *) q->q_ptr)->iid;
	sl_enable_con_t *p = (sl_enable_con_t *) mp->b_wptr;
	if (mp->b_wptr - mp->b_rptr < sizeof(*p))
		return -EPROTO;
	if (sl->state != SL_ENABLE_PENDING)
		return -EPROTO;
	sl->state = SL_ENABLED;
	if ((err = m2ua_sl_enabled(sl)))
		return (err);
	freemsg(mp);
	return (0);
}

/*
 *  SL_DISABLE_CON
 *  -------------------------------------------------------------------------
 */
static int sl_disable_con(queue_t * q, mblk_t * mp)
{
	slp_t *sl = ((sl_t *) q->q_ptr)->iid;
	sl_disable_con_t *p = (sl_disable_con_t *) mp->b_wptr;
	if (mp->b_wptr - mp->b_rptr < sizeof(*p))
		return -EMSGSIZE;
	if (sl->state != SL_DISABLE_PENDING)
		return -EPROTO;
	sl->state = SL_DISABLED;
	if ((err = m2ua_sl_disabled(sl)))
		return (err);
	freemsg(mp);
	return (0);
}

/*
 *  SL_OPTMGMT_ACK
 *  -------------------------------------------------------------------------
 */
static int sl_optmgmt_ack(queue_t * q, mblk_t * mp)
{
	(void) q;
	(void) mp;
	return -EPROTO;
}

/*
 *  SL_NOTIFY_IND
 *  -------------------------------------------------------------------------
 *  There are no M2UA messages to provide for events, statistics, or management
 *  reports.  We pass these indictions up as an M2UA_NOTIFY_IND to layer
 *  management so that it can deal with the messages.
 */
static int sl_notify_ind(queue_t * q, mblk_t * mp)
{
	int err;
	slp_t *sl = ((sl_t *) q->q_ptr)->iid;
	sl_notify_ind_t *p = (sl_notify_ind_t *) mp->b_wptr;
	m2ua_notify_ind_t *m;
	const caddr_t not_ptr = mp->b_rptr + p->notify_offset;
	const size_t not_len = mp->b_wptr - not_ptr;
	if (mp->b_wptr - mp->b_rptr < sizeof(*p))
		return -EMSGSIZE;
	if ((err = m2_link_notify_ind(sl->muxid, not_ptr, not_len)))
		return (err);
	freemsg(mp);
	return (0);
}

/*
 *  =========================================================================
 *
 *  SLU --> M2UA (ASP) Downstream Primitives
 *
 *  =========================================================================
 */

/*
 *  SL_INFO_REQ
 *  -------------------------------------------------------------------------
 *  The ASP has received an information request from the upper signalling link
 *  interface.  This must return information concerning the signalling link.
 */
static int sl_info_req(queue_t * q, mblk_t * mp)
{
	slp_t *sl = ((sl_t *) q->q_ptr)->iid;
	sl_info_req_t *p = (sl_info_req_t *) mp->b_rptr;
	if (mp->b_wptr - mp->b_rptr < sizeof(*p))
		return -EPROTO;
	return sl_info_ack(q);
}

/*
 *  SL_ATTACH_REQ
 *  -------------------------------------------------------------------------
 *  Should establish association if necessary and perform Link Key
 *  registration if necessary.
 *
 *  Signalling Links can be either PPA Type 1 or PPA Type 2.  When the
 *  signalling link is PPA Type 1, it requires that M2UA has already assigned
 *  a fixed Interface Identifier based on static configuration.  When the link
 *  is a PPA Type 2 signalling link, the stream uses the PPA to specify which
 *  SDTI/SDLI identifiers to use for dynamic registration to obtain an IID
 *  from the SGP.
 *
 *  The configuration daemon may have assigned more than one SGP for the
 *  signalling link.  Because it doesn't make too much sense to have other
 *  than an Override traffic mode towards a group of SGP, one of these SGP
 *  will be designated primary and the others secondary.
 *
 *  The attach only associates the SDTI/SDLI information with the stream and
 *  moves it to the SL_ATTACHED state.  The M2UA waits for the SL_ENABLE_REQ
 *  before attempting to establish association(s) with the SGP (as configured
 *  to do so by the configuration daemon).
 *
 *  Unfortunately, we might not be able to do too much error checking of the
 *  SDTI/SDLI values which are provided here.
 *
 */
static mblk_t *sl_attach_req(queue_t * q, mblk_t * mp)
{
	int err;
	slu_t *sl = ((sl_t *) q->q_ptr)->iid;
	sl_attach_req_t *p = (sl_attach_req_t *) mp->b_wptr;
	if (mp->b_wptr - mp->b_rptr < sizeof(*p) + sl->ppa_len)
		return -EPROTO;	/* maybe EMSGSIZE instead? */
	if (sl->state != SL_UNATTACHED)
		return -EPROTO;
	bcopy(mp->b_rptr + sizeof(*p), sl->ppa, sl->ppa_len);
	/* 
	 *  One check we can perform here is to see if any other signalling
	 *  link is attached to the specified SDTI/SDLI identifiers for a
	 *  given SG.  Only one signalling link can be attached
	 */
	return (0);
}

/*
 *  SL_DETACH_REQ
 *  -------------------------------------------------------------------------
 *  Here we are detaching the signalling link, perhaps in preparation for
 *  attaching the signalling link to another SDTI/SDLI pair if the signalling
 *  link is PPA Style 2.  PPA Style 1 signalling links don't need to be
 *  detached (but we might let them anyway).  Because we leave association(s)
 *  to SGP live, we may have to deregister interface identifiers (PPA Style
 *  2).  We can leave association(s) to SGP alive so that subsequent requiest
 *  to attach and enable the signalling link will not have to wait for
 *  association(s) to be established.  Actually, establishing association(s)
 *  might best be performed by layer management.
 */
static mblk_t *sl_detach_req(queue_t * q, mblk_t * mp)
{
}

/*
 *  SL_ENABLE_REQ
 *  -------------------------------------------------------------------------
 *  Should establish association(s) with the SGP which are associated with the
 *  signalling link by the configuration daemon (if association(s) are not
 *  already established by layer management).  Should register the ASP for the
 *  specified SDTI/SDLI identifiers and obtain an IID (if necessary, i.e.  PPA
 *  Style 2).  Should also move ASP to the Active state for the specified
 *  IIDs.  If any of these fail, the enable request fails by providing an
 *  error acknowledgement.
 *
 *  There are lot of things to do in this function.
 */
static mblk_t *sl_enable_req(queue_t * q, mblk_t * mp)
{
}

/*
 *  SL_DISABLE_REQ
 *  -------------------------------------------------------------------------
 *  Should move ASP to the Inactive state for the specified IIDs.
 */
static mblk_t *sl_disable_req(queue_t * q, mblk_t * mp)
{
}

/*
 *  =========================================================================
 *
 *  SL-User/SL-Provider --> M2UA MAUP Translator
 *
 *  =========================================================================
 *  Many of the messages of M2UA map directly onto SL primitives.  These
 *  message encoder functions take an SL primitive and return an M2UA message
 *  which is the direct equivalent of the primitive.  These functions are
 *  called by functions which service SL primitives.
 */
/*
 *  SL_DATA --> M2UA Data
 *  -------------------------------------------------------------------------
 */
static mblk_t *sl_data(queue_t * q, mblk_t * sdu)
{
	mblk_t *mp, *db = sdu;
	iid_t *sl = ((sl_t *) q->q_ptr)->iid;
	static const size_t mlen = M2UA_MAUP_SIZE + M2UA_PHDR_SIZE;
	if ((mp = allocb(mlen, BPRI_MED))) {
		const size_t dlen = db->b_wptr - db->b_rptr;
		mp->b_datap->db_type = M_DATA;
		*((uint32_t *) mp->b_wptr)++ = M2UA_MAUP_DATA;
		*((uint32_t *) mp->b_wptr)++ = htonl(mlen + dlen);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_IID;
		*((uint32_t *) mp->b_wptr)++ = htonl(sl->iid);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PHDR(M2UA_PARM_DATA1, dlen);
		mp->b_cont = db;
	}
	return (mp);
}

/*
 *  SL_PDU_IND --> M2UA	Data
 *  -------------------------------------------------------------------------
 */
static mblk_t *sl_pdu_req(queue_t * q, mblk_t * sdu)
{
	mblk_t *mp, *db = sdu->b_cont;
	iid_t *sl = ((sl_t *) q->q_ptr)->iid;
	static const size_t mlen = M2UA_MAUP_SIZE + M2UA_PHDR_SIZE;
	if ((mp = allocb(mlen, BPRI_MED))) {
		size_t dlen = msgdsize(db);
		mp->b_datap->db_type = M_DATA;
		*((uint32_t *) mp->b_wptr)++ = M2UA_MAUP_DATA;
		*((uint32_t *) mp->b_wptr)++ = htonl(mlen + dlen);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_IID;
		*((uint32_t *) mp->b_wptr)++ = htonl(sl->iid);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PHDR(M2UA_PARM_DATA1, dlen);
		mp->b_cont = db;
		freeb(sdu);
	}
	return (mp);
}

/*
 *  SL_EMERGENCY_REQ --> M2UA State Request
 *  -------------------------------------------------------------------------
 */
static mblk_t *sl_emergency_req(queue_t * q, mblk_t * sdu)
{
	mblk_t *mp;
	iid_t *sl = ((sl_t *) q->q_ptr)->iid;
	static const size_t mlen = M2UA_MAUP_SIZE + M2UA_PHDR_SIZE + sizeof(uint32_t);
	if ((mp = allocb(mlen, BPRI_MED))) {
		mp->b_datap->db_type = M_DATA;
		*((uint32_t *) mp->b_wptr)++ = M2UA_MAUP_STATE_REQ;
		*((uint32_t *) mp->b_wptr)++ = __constant_hotnl(mlen);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_IID;
		*((uint32_t *) mp->b_wptr)++ = htonl(sl->iid);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_STATE_REQUEST;
		*((uint32_t *) mp->b_wptr)++ = M2UA_STATUS_EMER_SET;
		freemsg(sdu);
	}
	return (mp);
}

/*
 *  SL_EMERGENCY_CEASES_REQ --> M2UA State Request
 *  -------------------------------------------------------------------------
 */
static mblk_t *sl_emergency_ceases_req(queue_t * q, mblk_t * sdu)
{
	mblk_t *mp;
	iid_t *sl = ((sl_t *) q->q_ptr)->iid;
	static const size_t mlen = M2UA_MAUP_SIZE + M2UA_PHDR_SIZE + sizeof(uint32_t);
	if ((mp = allocb(mlen, BPRI_MED))) {
		mp->b_datap->db_type = M_DATA;
		*((uint32_t *) mp->b_wptr)++ = M2UA_MAUP_STATE_REQ;
		*((uint32_t *) mp->b_wptr)++ = __constant_hotnl(mlen);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_IID;
		*((uint32_t *) mp->b_wptr)++ = htonl(sl->iid);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_STATE_REQUEST;
		*((uint32_t *) mp->b_wptr)++ = M2UA_STATUS_EMER_CLEAR;
		freemsg(sdu);
	}
	return (mp);
}

/*
 *  SL_START_REQ --> M2UA Establish Request
 *  -------------------------------------------------------------------------
 */
static mblk_t *sl_start_req(queue_t * q, mblk_t * sdu)
{
	mblk_t *mp;
	iid_t *sl = ((sl_t *) q->q_ptr)->iid;
	static const size_t mlen = M2UA_MAUP_SIZE;
	if ((mp = allocb(mlen, BPRI_MED))) {
		mp->b_datap->db_type = M_DATA;
		*((uint32_t *) mp->b_wptr)++ = M2UA_MAUP_ESTAB_REQ;
		*((uint32_t *) mp->b_wptr)++ = __constant_hotnl(mlen);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_IID;
		*((uint32_t *) mp->b_wptr)++ = htonl(sl->iid);
		freemsg(sdu);
	}
	return (mp);
}

/*
 *  SL_STOP_REQ --> M2UA Release Request
 *  -------------------------------------------------------------------------
 */
static mblk_t *sl_stop_req(queue_t * q, mblk_t * sdu)
{
	mblk_t *mp;
	iid_t *sl = ((sl_t *) q->q_ptr)->iid;
	static const size_t mlen = M2UA_MAUP_SIZE;
	if ((mp = allocb(mlen, BPRI_MED))) {
		mp->b_datap->db_type = M_DATA;
		*((uint32_t *) mp->b_wptr)++ = M2UA_MAUP_REL_REQ;
		*((uint32_t *) mp->b_wptr)++ = __constant_hotnl(mlen);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_IID;
		*((uint32_t *) mp->b_wptr)++ = htonl(sl->iid);
		freemsg(sdu);
	}
	return (mp);
}

/*
 *  SL_RETRIEVE_BSNT_REQ --> M2UA Retrieve Request
 *  -------------------------------------------------------------------------
 */
static mblk_t *sl_retrieve_bsnt_req(queue_t * q, mblk_t * sdu)
{
	mblk_t *mp;
	iid_t *sl = ((sl_t *) q->q_ptr)->iid;
	static const size_t mlen = M2UA_MAUP_SIZE + M2UA_PHDR_SIZE + sizeof(uint32_t);
	if ((mp = allocb(mlen, BPRI_MED))) {
		mp->b_datap->db_type = M_DATA;
		*((uint32_t *) mp->b_wptr)++ = M2UA_MAUP_RETR_REQ;
		*((uint32_t *) mp->b_wptr)++ = __constant_hotnl(mlen);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_IID;
		*((uint32_t *) mp->b_wptr)++ = htonl(sl->iid);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_ACTION;
		*((uint32_t *) mp->b_wptr)++ = M2UA_ACTION_RTRV_BSN;
		freemsg(sdu);
	}
	return (mp);
}

/*
 *  SL_RETRIEVAL_REQUEST_AND_FSNC_REQ --> M2UA Retrieve Request
 *  -------------------------------------------------------------------------
 */
static mblk_t *sl_retrieval_request_and_fsnc_req(queue_t * q, mblk_t * sdu)
{
	mblk_t *mp;
	iid_t *sl = ((sl_t *) q->q_ptr)->iid;
	static const size_t mlen = M2UA_MAUP_SIZE + 2 * (M2UA_PHDR_SIZE + sizeof(uint32_t));
	if ((mp = allocb(mlen, BPRI_MED))) {
		sl_retrieval_req_and_fsnc_t *p =
		    (sl_retrieval_request_and_fsnc_req_t *) sdu->b_rptr;
		mp->b_datap->db_type = M_DATA;
		*((uint32_t *) mp->b_wptr)++ = M2UA_MAUP_RETR_REQ;
		*((uint32_t *) mp->b_wptr)++ = __constant_hotnl(mlen);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_IID;
		*((uint32_t *) mp->b_wptr)++ = htonl(sl->iid);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_ACTION;
		*((uint32_t *) mp->b_wptr)++ = M2UA_ACTION_RTRV_MSGS;
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_SEQNO;
		*((uint32_t *) mp->b_wptr)++ = htonl(p->fsnc);
		freemsg(sdu);
	}
	return (mp);
}

/*
 *  SL_RESUME_REQ --> M2UA State Request
 *  -------------------------------------------------------------------------
 */
static mblk_t *sl_resume_req(queue_t * q, mblk_t * sdu)
{
	mblk_t *mp;
	iid_t *sl = ((sl_t *) q->q_ptr)->iid;
	static const size_t mlen = M2UA_MAUP_SIZE + 2 * (M2UA_PHDR_SIZE + sizeof(uint32_t));
	if ((mp = allocb(mlen, BPRI_MED))) {
		mp->b_datap->db_type = M_DATA;
		*((uint32_t *) mp->b_wptr)++ = M2UA_MAUP_STATE_REQ;
		*((uint32_t *) mp->b_wptr)++ = __constant_hotnl(mlen);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_IID;
		*((uint32_t *) mp->b_wptr)++ = htonl(sl->iid);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_STATE_REQUEST;
		*((uint32_t *) mp->b_wptr)++ = M2UA_STATUS_CONTINUE;
		freemsg(sdu);
	}
	return (mp);
}

/*
 *  SL_CLEAR_BUFFERS_REQ --> M2UA State Request
 *  -------------------------------------------------------------------------
 */
static mblk_t *sl_clear_buffers_req(queue_t * q, mblk_t * sdu)
{
	mblk_t *mp;
	iid_t *sl = ((sl_t *) q->q_ptr)->iid;
	static const size_t mlen = M2UA_MAUP_SIZE + M2UA_PHDR_SIZE + sizeof(uint32_t);
	if ((mp = allocb(mlen, BPRI_MED))) {
		mp->b_datap->db_type = M_DATA;
		*((uint32_t *) mp->b_wptr)++ = M2UA_MAUP_STATE_REQ;
		*((uint32_t *) mp->b_wptr)++ = __constant_hotnl(mlen);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_IID;
		*((uint32_t *) mp->b_wptr)++ = htonl(sl->iid);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_STATE_REQUEST;
		*((uint32_t *) mp->b_wptr)++ = M2UA_STATUS_FLUSH_BUFFERS;
		freemsg(sdu);
	}
	return (mp);
}

/*
 *  SL_CLEAR_RTB_REQ --> M2UA Retrieve Request
 *  -------------------------------------------------------------------------
 */
static mblk_t *sl_clear_rtb_req(queue_t * q, mblk_t * sdu)
{
	mblk_t *mp;
	iid_t *sl = ((sl_t *) q->q_ptr)->iid;
	static const size_t mlen = M2UA_MAUP_SIZE + M2UA_PHDR_SIZE + sizeof(uint32_t);
	if ((mp = allocb(mlen, BPRI_MED))) {
		mp->b_datap->db_type = M_DATA;
		*((uint32_t *) mp->b_wptr)++ = M2UA_MAUP_RETR_REQ;
		*((uint32_t *) mp->b_wptr)++ = __constant_hotnl(mlen);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_IID;
		*((uint32_t *) mp->b_wptr)++ = htonl(sl->iid);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_ACTION;
		*((uint32_t *) mp->b_wptr)++ = M2UA_ACTION_DROP_MSGS;
		freemsg(sdu);
	}
	return (mp);
}

/*
 *  SL_LOCAL_PROCESOR_OUTAGE_REQ --> M2UA State Request
 *  -------------------------------------------------------------------------
 */
static mblk_t *sl_local_processor_outage_req(queue_t * q, mblk_t * sdu)
{
	mblk_t *mp;
	iid_t *sl = ((sl_t *) q->q_ptr)->iid;
	static const size_t mlen = M2UA_MAUP_SIZE + M2UA_PHDR_SIZE + sizeof(uint32_t);
	if ((mp = allocb(mlen, BPRI_SIZE))) {
		mp->b_datap->db_type = M_DATA;
		*((uint32_t *) mp->b_wptr)++ = M2UA_MAUP_STATE_REQ;
		*((uint32_t *) mp->b_wptr)++ = __constant_hotnl(mlen);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_IID;
		*((uint32_t *) mp->b_wptr)++ = htonl(sl->iid);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_STATE_REQUEST;
		*((uint32_t *) mp->b_wptr)++ = M2UA_STATUS_LPO_SET;
		freemsg(sdu);
	}
	return (mp);
}

/*
 *  SL_CONGESTION_DISCARD_REQ --> M2UA State Request
 *  -------------------------------------------------------------------------
 */
static mblk_t *sl_congestion_discard_req(queue_t * q, mblk_t * sdu)
{
	mblk_t *mp;
	iid_t *sl = ((sl_t *) q->q_ptr)->iid;
	static const size_t mlen = M2UA_MAUP_SIZE + M2UA_PDHR_SIZE + sizeof(uint32_t);
	if ((mp = allocb(mlen, BPRI_MED))) {
		mp->b_datap->db_type = M_DATA;
		*((uint32_t *) mp->b_wptr)++ = M2UA_MAUP_STATE_REQ;
		*((uint32_t *) mp->b_wptr)++ = __constant_hotnl(mlen);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_IID;
		*((uint32_t *) mp->b_wptr)++ = htonl(sl->iid);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_STATE_REQUEST;
		*((uint32_t *) mp->b_wptr)++ = M2UA_STATUS_CONG_DISCARD;
		freemsg(sdu);
	}
	return (mp);
}

/*
 *  SL_CONGESTION_ACCEPT_REQ --> M2UA State Request
 *  -------------------------------------------------------------------------
 */
static mblk_t *sl_congestion_accept_req(queue_t * q, mblk_t * sdu)
{
	mblk_t *mp;
	iid_t *sl = ((sl_t *) q->q_ptr)->iid;
	static const size_t mlen = M2UA_MAUP_SIZE + M2UA_PDHR_SIZE + sizeof(uint32_t);
	if ((mp = allocb(mlen, BPRI_MED))) {
		mp->b_datap->db_type = M_DATA;
		*((uint32_t *) mp->b_wptr)++ = M2UA_MAUP_STATE_REQ;
		*((uint32_t *) mp->b_wptr)++ = __constant_hotnl(mlen);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_IID;
		*((uint32_t *) mp->b_wptr)++ = htonl(sl->iid);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_STATE_REQUEST;
		*((uint32_t *) mp->b_wptr)++ = M2UA_STATUS_CONG_ACCEPT;
		freemsg(sdu);
	}
	return (mp);
}

/*
 *  SL_NO_CONGESTION_REQ --> M2UA State Request
 *  -------------------------------------------------------------------------
 */
static mblk_t *sl_no_congestion_req(queue_t * q, mblk_t * sdu)
{
	mblk_t *mp;
	iid_t *sl = ((sl_t *) q->q_ptr)->iid;
	static const size_t mlen = M2UA_MAUP_SIZE + M2UA_PDHR_SIZE + sizeof(uint32_t);
	if ((mp = allocb(mlen, BPRI_MED))) {
		mp->b_datap->db_type = M_DATA;
		*((uint32_t *) mp->b_wptr)++ = M2UA_MAUP_STATE_REQ;
		*((uint32_t *) mp->b_wptr)++ = __constant_hotnl(mlen);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_IID;
		*((uint32_t *) mp->b_wptr)++ = htonl(sl->iid);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_STATE_REQUEST;
		*((uint32_t *) mp->b_wptr)++ = M2UA_STATUS_CONG_CLEAR;
		freemsg(sdu);
	}
	return (mp);
}

/*
 *  SL_POWER_ON_REQ --> M2UA
 *  -------------------------------------------------------------------------
 */
static mblk_t *sl_power_on_req(queue_t * q, mblk_t * sdu)
{
	(void) q;
	(void) sdu;
	freemsg(sdu);
	return (0);
}

/*
 *  SL_PDU_IND --> M2UA	Data
 *  -------------------------------------------------------------------------
 */
static mblk_t *sl_pdu_ind(queue_t * q, mblk_t * sdu)
{
	mblk_t *mp, *db = sdu->b_cont;
	iid_t *sl = ((sl_t *) q->q_ptr)->iid;
	static const size_t mlen = M2UA_MAUP_SIZE + M2UA_PHDR_SIZE;
	if ((mp = allocb(mlen, BPRI_MED))) {
		const size_t dlen = db->b_wptr - db->b_rptr;
		mp->b_datap->db_type = M_DATA;
		*((uint32_t *) mp->b_wptr)++ = M2UA_MAUP_DATA;
		*((uint32_t *) mp->b_wptr)++ = htonl(mlen + dlen);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_IID;
		*((uint32_t *) mp->b_wptr)++ = htonl(sl->iid);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PHDR(M2UA_PARM_DATA1, dlen);
		mp->b_cont = db;
		freeb(sdu);
	}
	return (mp);
}

/*
 *  SL_LINK_CONGESTED_IND --> M2UA Congestion Indication
 *  -------------------------------------------------------------------------
 */
static mblk_t *sl_link_congested_ind(queue_t * q, mblk_t * sdu)
{
	mblk_t *mp;
	iid_t *sl = ((sl_t *) q->q_ptr)->iid;
	static const size_t mlen = M2UA_MAUP_SIZE + 2 * (M2UA_PHDR_SIZE + sizeof(uint32_t));
	if ((mp = allocb(mlen, BPRI_MED))) {
		sl_link_congested_ind_t *p = (sl_link_congested_ind_t *) sdu->b_rptr;
		mp->b_datap->db_type = M_DATA;
		*((uint32_t *) mp->b_wptr)++ = M2UA_MAUP_CONG_IND;
		*((uint32_t *) mp->b_wptr)++ = __constant_htonl(mlen);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_IID;
		*((uint32_t *) mp->b_wptr)++ = htonl(sl->iid);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_CONG_STATUS;
		*((uint32_t *) mp->b_wptr)++ = htonl(p->cong_status);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_DISC_STATUS;
		*((uint32_t *) mp->b_wptr)++ = htonl(p->disc_status);
		freemsg(sdu);
	}
	return (mp);
}

/*
 *  SL_LINK_CONGESTION_CEASED_IND --> M2UA Congestion Indication
 *  -------------------------------------------------------------------------
 */
static mblk_t *sl_link_congestion_ceased_ind(queue_t * q, mblk_t * sdu)
{
	mblk_t *mp;
	iid_t *sl = ((sl_t *) q->q_ptr)->iid;
	static const size_t mlen = M2UA_MAUP_SIZE + 2 * (M2UA_PHDR_SIZE + sizeof(uint32_t));
	if ((mp = allocb(mlen, BPRI_MED))) {
		sl_link_congestion_ceased_ind_t *p =
		    (sl_link_congestion_ceased_ind_t *) sdu->b_rptr;
		mp->b_datap->db_type = M_DATA;
		*((uint32_t *) mp->b_wptr)++ = M2UA_MAUP_CONG_IND;
		*((uint32_t *) mp->b_wptr)++ = __constant_htonl(mlen);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_IID;
		*((uint32_t *) mp->b_wptr)++ = htonl(sl->iid);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_CONG_STATUS;
		*((uint32_t *) mp->b_wptr)++ = htonl(p->cong_status);
		*((uint32_t *) mp->b_wptr)++ = M2UA_PARM_DISC_STATUS;
		*((uint32_t *) mp->b_wptr)++ = htonl(p->disc_status);
		freemsg(sdu);
	}
	return (mp);
}

/*
 *  SL_RETRIEVED_MESSAGE_IND --> M2UA Retrieval Indication
 *  -------------------------------------------------------------------------
 */
static mblk_t *sl_retrieved_message_ind(queue_t * q, mblk_t * sdu)
{
	mblk_t *mp, *db = sdu->b_cont;
	iid_t *sl = ((sl_t *) q->q_ptr)->iid;
	static const size_t mlen = M2UA_MAUP_SIZE + M2UA_PHDR_SIZE;
	if ((mp = allocb(mlen, BPRI_MED))) {
		const size_t dlen = db->b_wptr - db->b_rptr;
		mp->b_datap->db_type = M_DATA;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_MAUP_RETR_IND;
		*((uint32_t *) mp->b_wtpr)++ = htonl(mlen + dlen);
		*((uint32_t *) mp->b_wtpr)++ = M2UA_PARM_IID;
		*((uint32_t *) mp->b_wtpr)++ = htonl(sl->iid);
		*((uint32_t *) mp->b_wtpr)++ = M2UA_PHDR(M2UA_PARM_DATA1, dlen);
		mp->b_cont = db;
		freeb(sdu);
	}
	return (mp);
}

/*
 *  SL_RETRIEVAL_COMPLETED_IND --> M2UA Retrieval Complete Indication
 *  -------------------------------------------------------------------------
 */
static mblk_t *sl_retrieval_completed_ind(queue_t * q, mblk_t * sdu)
{
	mblk_t *mp;
	iid_t *sl = ((sl_t *) q->q_ptr)->iid;
	static const size_t mlen = M2UA_MAUP_SIZE + 2 * (M2UA_PHDR_SIZE + sizeof(uint32_t));
	if ((mp = allocb(mlen, BPRI_MED))) {
		mp->b_datap->db_type = M_DATA;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_MAUP_RETR_COMP_IND;
		*((uint32_t *) mp->b_wtpr)++ = __constant_htonl(mlen);
		*((uint32_t *) mp->b_wtpr)++ = M2UA_PARM_IID;
		*((uint32_t *) mp->b_wtpr)++ = htonl(sl->iid);
		*((uint32_t *) mp->b_wtpr)++ = M2UA_PARM_ACTION;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_ACTION_RTRV_MSGS;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_PARM_RETR_RESULT;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_RESULT_SUCCESS;
		freemsg(sdu);
	}
	return (mp);
}

/*
 *  SL_RB_CLEARED_IND --> M2UA State Confirm
 *  -------------------------------------------------------------------------
 */
static mblk_t *sl_rb_cleared_ind(queue_t * q, mblk_t * sdu)
{
	mblk_t *mp;
	iid_t *sl = ((sl_t *) q->q_ptr)->iid;
	static const size_t mlen = M2UA_MAUP_SIZE + 2 * (M2UA_PHDR_SIZE + sizeof(uint32_t));
	if ((mp = allocb(mlen, BPRI_MED))) {
		mp->b_datap->db_type = M_DATA;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_MAUP_STATE_CON;
		*((uint32_t *) mp->b_wtpr)++ = __constant_htonl(mlen);
		*((uint32_t *) mp->b_wtpr)++ = M2UA_PARM_IID;
		*((uint32_t *) mp->b_wtpr)++ = htonl(sl->iid);
		*((uint32_t *) mp->b_wtpr)++ = M2UA_PARM_STATE_REQUEST;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_STATUS_FLUSH_BUFFERS;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_PARM_STATE_RESULT;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_RESULT_SUCCESS;
		freemsg(sdu);
	}
	return (mp);
}

/*
 *  SL_BSNT_IND --> M2UA State Confirm
 *  -------------------------------------------------------------------------
 */
static mblk_t *sl_bsnt_ind(queue_t * q, mblk_t * sdu)
{
	mblk_t *mp;
	iid_t *sl = ((sl_t *) q->q_ptr)->iid;
	static const size_t mlen = M2UA_MAUP_SIZE + 3 * (M2UA_PHDR_SIZE + sizeof(uint32_t));
	if ((mp = allocb(mlen, BPRI_MED))) {
		sl_bsnt_ind_t *p = (sl_bsnt_ind_t *) sdu->b_rptr;
		mp->b_datap->db_type = M_DATA;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_MAUP_STATE_CON;
		*((uint32_t *) mp->b_wtpr)++ = __constant_htonl(mlen);
		*((uint32_t *) mp->b_wtpr)++ = M2UA_PARM_IID;
		*((uint32_t *) mp->b_wtpr)++ = htonl(sl->iid);
		*((uint32_t *) mp->b_wtpr)++ = M2UA_PARM_ACTION;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_ACTION_RTRV_BSN;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_PARM_RETR_RESULT;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_RESULT_SUCCESS;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_PARM_SEQNO * ((uint32_t *) mp->b_wtpr)++ =
		    htonl(p->bsnt);
		freemsg(sdu);
	}
	return (mp);
}

/*
 *  SL_IN_SERVICE_IND --> M2UA Establish Confirmation
 *  -------------------------------------------------------------------------
 */
static mblk_t *sl_in_service_ind(queue_t * q, mblk_t * sdu)
{
	mblk_t *mp;
	iid_t *sl = ((sl_t *) q->q_ptr)->iid;
	static const size_t mlen = M2UA_MAUP_SIZE;
	if ((mp = allocb(mlen, BPRI_MED))) {
		mp->b_datap->db_type = M_DATA;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_MAUP_ESTAB_CON;
		*((uint32_t *) mp->b_wtpr)++ = __constant_htonl(mlen);
		*((uint32_t *) mp->b_wtpr)++ = M2UA_PARM_IID;
		*((uint32_t *) mp->b_wtpr)++ = htonl(sl->iid);
		freemsg(sdu);
	}
	return (mp);
}

/*
 *  SL_OUT_OF_SERVICE_IND --> M2UA Release Indication
 *  -------------------------------------------------------------------------
 */
static mblk_t *sl_out_of_service_ind(queue_t * q, mblk_t * sdu)
{
	mblk_t *mp;
	iid_t *sl = ((sl_t *) q->q_ptr)->iid;
	static const size_t mlen = M2UA_MAUP_SIZE;
	if ((mp = allocb(mlen, BPRI_MED))) {
		mp->b_datap->db_type = M_DATA;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_MAUP_REL_IND;
		*((uint32_t *) mp->b_wtpr)++ = __constant_htonl(mlen);
		*((uint32_t *) mp->b_wtpr)++ = M2UA_PARM_IID;
		*((uint32_t *) mp->b_wtpr)++ = htonl(sl->iid);
		freemsg(sdu);
	}
	return (mp);
}

/*
 *  SL_REMOTE_PROCESSOR_OUTAGE_IND --> M2UA State Indication
 *  -------------------------------------------------------------------------
 */
static mblk_t *sl_remote_processor_outage_ind(queue_t * q, mblk_t * sdu)
{
	mblk_t *mp;
	iid_t *sl = ((sl_t *) q->q_ptr)->iid;
	static const size_t mlen = M2UA_MAUP_SIZE + M2UA_PDHR_SIZE + sizeof(uint32_t);
	if ((mp = allocb(mlen, BPRI_MED))) {
		mp->b_datap->db_type = M_DATA;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_MAUP_STATE_IND;
		*((uint32_t *) mp->b_wtpr)++ = __constant_htonl(mlen);
		*((uint32_t *) mp->b_wtpr)++ = M2UA_PARM_IID;
		*((uint32_t *) mp->b_wtpr)++ = htonl(sl->iid);
		*((uint32_t *) mp->b_wtpr)++ = M2UA_PARM_STATE_EVENT;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_EVENT_RPO_ENTER;
		freemsg(sdu);
	}
	return (mp);
}

/*
 *  SL_REMOTE_PROCESSOR_RECOVERED_IND --> M2UA State Indication
 *  -------------------------------------------------------------------------
 */
static mblk_t *sl_remote_processor_recovered_ind(queue_t * q, mblk_t * sdu)
{
	mblk_t *mp;
	iid_t *sl = ((sl_t *) q->q_ptr)->iid;
	static const size_t mlen = M2UA_MAUP_SIZE + M2UA_PHDR_SIZE + sizeof(uint32_t);
	if ((mp = allocb(mlen, BPRI_MED))) {
		mp->b_datap->db_type = M_DATA;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_MAUP_STATE_IND;
		*((uint32_t *) mp->b_wtpr)++ = __constant_htonl(mlen);
		*((uint32_t *) mp->b_wtpr)++ = M2UA_PARM_IID;
		*((uint32_t *) mp->b_wtpr)++ = htonl(sl->iid);
		*((uint32_t *) mp->b_wtpr)++ = M2UA_PARM_STATE_EVENT;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_EVENT_RPO_EXIT;
		freemsg(sdu);
	}
	return (mp);
}

/*
 *  SL_RTB_CLEARED_IND --> M2UA Retrieve Confirmation
 *  -------------------------------------------------------------------------
 */
static mblk_t *sl_rtb_cleared_ind(queue_t * q, mblk_t * sdu)
{
	mblk_t *mp;
	iid_t *sl = ((sl_t *) q->q_ptr)->iid;
	static const size_t mlen = M2UA_MAUP_SIZE + 2 * (M2UA_PHDR_SIZE + sizeof(uint32_t));
	if ((mp = allocb(mlen, BPRI_MED))) {
		mp->b_datap->db_type = M_DATA;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_MAUP_RETR_CON;
		*((uint32_t *) mp->b_wtpr)++ = __constant_htonl(mlen);
		*((uint32_t *) mp->b_wtpr)++ = M2UA_PARM_IID;
		*((uint32_t *) mp->b_wtpr)++ = htonl(sl->iid);
		*((uint32_t *) mp->b_wtpr)++ = M2UA_PARM_ACTION;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_ACTION_DROP_MSGS;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_PARM_RETR_RESULT;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_RESULT_SUCCESS;
		freemsg(sdu);
	}
	return (mp);
}

/*
 *  SL_RETRIEVAL_NOT_POSSIBLE_IND --> M2UA Retrieve Confirmation
 *  -------------------------------------------------------------------------
 */
static mblk_t *sl_retrieval_not_possible_ind(queue_t * q, mblk_t * sdu)
{
	mblk_t *mp;
	iid_t *sl = ((sl_t *) q->q_ptr)->iid;
	static const size_t mlen = M2UA_MAUP_SIZE + 2 * (M2UA_PHDR_SIZE + sizeof(uint32_t));
	if ((mp = allocb(mlen, BPRI_MED))) {
		mp->b_datap->db_type = M_DATA;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_MAUP_RETR_CON;
		*((uint32_t *) mp->b_wtpr)++ = __constant_htonl(mlen);
		*((uint32_t *) mp->b_wtpr)++ = M2UA_PARM_IID;
		*((uint32_t *) mp->b_wtpr)++ = htonl(sl->iid);
		*((uint32_t *) mp->b_wtpr)++ = M2UA_PARM_ACTION;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_ACTION_RTRV_MSGS;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_PARM_RETR_RESULT;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_RESULT_FAILURE;
		freemsg(sdu);
	}
	return (mp);
}

/*
 *  SL_BSNT_NOT_RETRIEVABLE_IND --> M2UA Retrieve Confirmation
 *  -------------------------------------------------------------------------
 */
static mblk_t *sl_bsnt_not_retrievable_ind(queue_t * q, mblk_t * sdu)
{
	mblk_t *mp;
	iid_t *sl = ((sl_t *) q->q_ptr)->iid;
	static const size_t mlen = M2UA_MHDR_SIZE + 3 * (M2UA_PHDR_SIZE + sizeof(uint32_t));
	if ((mp = allocb(mlen, BPRI_MED))) {
		mp->b_datap->db_type = M_DATA;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_MAUP_STATE_CON;
		*((uint32_t *) mp->b_wtpr)++ = __constant_htonl(mlen);
		*((uint32_t *) mp->b_wtpr)++ = M2UA_PARM_IID;
		*((uint32_t *) mp->b_wtpr)++ = htonl(sl->iid);
		*((uint32_t *) mp->b_wtpr)++ = M2UA_PARM_ACTION;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_ACTION_RTRV_BSN;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_PARM_RETR_RESULT;
		*((uint32_t *) mp->b_wtpr)++ = M2UA_RESULT_FAILURE;
		freemsg(sdu);
	}
	return (mp);
}

/*
 *  Translation mapping.
 *  -------------------------------------------------------------------------
 *  The following array of function pointers maps an SL primtitive onto the
 *  function (above) which translates it into an M2UA message suitable for
 *  transmission on a transport stream to the appropriate ASP/SGP/SPP.
 */
static mblk_t *(*sl_xlat[]) (const queue_t *, const mblk_t *) = {
	NULL,			/* SL_INFO_REQ */
	    NULL,		/* SL_ATTACH_REQ */
	    NULL,		/* SL_DETACH_REQ */
	    NULL,		/* SL_ENABLE_REQ */
	    NULL,		/* SL_DISABLE_REQ */
	    NULL,		/* SL_OPTMGMT_REQ */
	    NULL,		/* SL_NOTIFY_REQ */
	    sl_pdu_req,		/* SL_PDU_REQ */
	    sl_emergency_req,	/* SL_EMERGENCY_REQ */
	    sl_emergency_ceases_req,	/* SL_EMERGENCY_CEASES_REQ */
	    sl_start_req,	/* SL_START_REQ */
	    sl_stop_req,	/* SL_STOP_REQ */
	    sl_retrieve_bsnt_req,	/* SL_RETRIEVE_BSNT_REQ */
	    sl_retrieval_request_and_fsnc_req,	/* SL_RETRIEVAL_REQUEST_AND_FSNC_REQ */
	    sl_resume_req,	/* SL_RESUME_REQ */
	    sl_clear_buffers_req,	/* SL_CLEAR_BUFFERS_REQ */
	    sl_clear_rtb_req,	/* SL_CLEAR_RTB_REQ */
	    sl_local_processor_outage_req,	/* SL_LOCAL_PROCESSOR_OUTAGE_REQ */
	    sl_congestion_discard_req,	/* SL_CONGESTION_DISCARD_REQ */
	    sl_congestion_accept_req,	/* SL_CONGESTION_ACCEPT_REQ */
	    sl_no_congestion_req,	/* SL_NO_CONGESTION_REQ */
	    NULL,		/* SL_POWER_ON_REQ */
	    NULL,		/* SL_INFO_ACK */
	    NULL,		/* SL_OK_ACK */
	    NULL,		/* SL_ERROR_ACK */
	    NULL,		/* SL_ENABLE_CON */
	    NULL,		/* SL_DISABLE_CON */
	    NULL,		/* SL_OPTMGMT_ACK */
	    NULL,		/* SL_NOTIFY_IND */
	    sl_pdu_ind,		/* SL_PDU_IND */
	    sl_link_congested_ind,	/* SL_LINK_CONGESTED_IND */
	    sl_link_congestion_ceased_ind,	/* SL_LINK_CONGESTION_CEASED_IND */
	    sl_retrieved_message_ind,	/* SL_RETRIEVED_MESSAGE_IND */
	    sl_rb_cleared_ind,	/* SL_RB_CLEARED_IND */
	    sl_bsnt_ind,	/* SL_BSNT_IND */
	    sl_in_service_ind,	/* SL_IN_SERVICE_IND */
	    sl_out_of_service_ind,	/* SL_OUT_OF_SERVICE_IND */
	    sl_remote_processor_outage_ind,	/* SL_REMOTE_PROCESSOR_OUTAGE_IND */
	    sl_remote_processor_recovered_ind,	/* SL_REMOTE_PROCESSOR_RECOVERED_IND */
	    sl_rtb_cleared_ind,	/* SL_RTB_CLEARED_IND */
	    sl_retrieval_not_possible_ind,	/* SL_RETRIEVAL_NOT_POSSIBLE_IND */
	    sl_bsnt_not_retrievable_ind	/* SL_BSNT_NOT_RETRIEVABLE_IND */
};

/*
 *  This function not only translates an SL primitive into an M2UA message,
 *  but it also writes that message to the q->q_next pointer associated with
 *  the SLU/SLP.  It is the responsibility of the multiplexing driver to
 *  switch the q->q_next pointers on the SLU/SLP streams when a new...
 *
 *  No. that won't work.  primarily for broadcast and loadshare modes.  FIXME:
 *  it will be necessary to have this function look up the appropriate next
 *  ASP/SGP/SPP queue on which to send the message.  This should not be a
 *  problem, however, as each SLU/SLP maps to an AS/SG/SP and from that
 *  structure we can determine which ASP/SGP/SPP is active and carrying
 *  traffic.
 */
static int sl_translate(queue_t * q, mblk_t * mp)
{
	int err = -EOPNOTSUPP;
	int prim = *((long *) mp->b_rptr);
	if (0 <= prim && prim < sizeof(sl_xlat) / sizeof(int (*)()) && sl_xlat[prim]) {
		mblk_t *np;
		if (!(np = (*sl_xlat[prim]) (q, mp)))
			return (-ENOBUFS);
		if ((err = m2ua_as_write(q, np)))
			return (err);
		return (0);
	}
	return (err);
}
static int (*sl_prim[]) (const queue_t *, const mblk_t *) = {
#define S_DSTR_FIRST	SL_INFO_REQ
	lm_link_ind,		/* SL_INFO_REQ 0 */
	    lm_link_ind,	/* SL_ATTACH_REQ 1 */
	    lm_link_ind,	/* SL_DETACH_REQ 2 */
	    lm_link_ind,	/* SL_ENABLE_REQ 3 */
	    lm_link_ind,	/* SL_DISABLE_REQ 4 */
	    lm_link_ind,	/* SL_OPTMGMT_REQ 5 */
	    lm_link_ind,	/* SL_NOTIFY_REQ 6 */
	    sl_translate,	/* SL_PDU_REQ 7 */
	    sl_translate,	/* SL_EMERGENCY_REQ 8 */
	    sl_translate,	/* SL_EMERGENCY_CEASES_REQ 9 */
	    sl_translate,	/* SL_START_REQ 10 */
	    sl_translate,	/* SL_STOP_REQ 11 */
	    sl_translate,	/* SL_RETRIEVE_BSNT_REQ 12 */
	    sl_translate,	/* SL_RETRIEVAL_REQUEST_AND_FSNC_REQ 13 */
	    sl_translate,	/* SL_RESUME_REQ 14 */
	    sl_translate,	/* SL_CLEAR_BUFFERS_REQ 15 */
	    sl_translate,	/* SL_CLEAR_RTB_REQ 16 */
	    sl_translate,	/* SL_LOCAL_PROCESSOR_OUTAGE_REQ 17 */
	    sl_translate,	/* SL_CONGESTION_DISCARD_REQ 18 */
	    sl_translate,	/* SL_CONGESTION_ACCEPT_REQ 19 */
	    sl_translate,	/* SL_NO_CONGESTION_REQ 20 */
	    lm_link_ind,	/* SL_POWER_ON_REQ 21 */
#define S_DSTR_LAST	SL_POWER_ON_REQ
#define S_USTR_FIRST	SL_INFO_ACK
	    lm_link_ind,	/* SL_INFO_ACK 22 */
	    lm_link_ind,	/* SL_OK_ACK 23 */
	    lm_link_ind,	/* SL_ERROR_ACK 24 */
	    lm_link_ind,	/* SL_ENABLE_CON 25 */
	    lm_link_ind,	/* SL_DISABLE_CON 26 */
	    lm_link_ind,	/* SL_OPTMGMT_ACK 27 */
	    lm_link_ind,	/* SL_NOTIFY_IND 28 */
	    sl_translate,	/* SL_PDU_IND 29 */
	    sl_translate,	/* SL_LINK_CONGESTED_IND 30 */
	    sl_translate,	/* SL_LINK_CONGESTION_CEASED_IND 31 */
	    sl_translate,	/* SL_RETRIEVED_MESSAGE_IND 32 */
	    sl_translate,	/* SL_RB_CLEARED_IND 33 */
	    sl_translate,	/* SL_BSNT_IND 34 */
	    sl_translate,	/* SL_IN_SERVICE_IND 35 */
	    sl_translate,	/* SL_OUT_OF_SERVICE_IND 36 */
	    sl_translate,	/* SL_REMOTE_PROCESSOR_OUTAGE_IND 37 */
	    sl_translate,	/* SL_REMOTE_PROCESSOR_RECOVERED_IND 38 */
	    sl_translate,	/* SL_RTB_CLEARED_IND 39 */
	    sl_translate,	/* SL_RETRIEVAL_NOT_POSSIBLE_IND 30 */
	    sl_translate	/* SL_BSNT_NOT_RETRIEVABLE_IND 31 */
#define S_USTR_FIRST	SL_BSNT_NOT_RETRIEVABLE_IND
};

/*
 *  M_DATA Processing
 *  -------------------------------------------------------------------------
 */
static int ss7_w_data(queue_t * q, mblk_t * msg)
{
	int err;
	mblk_t *np;
	if (!(np = sl_data(q, msg)))
		return (-ENOBUFS);
	if ((err = m2ua_as_write(q, np)))
		return (err);
	return (0);
}

int ss7_r_data(queue_t * q, mblk_t * msg)
{
	int err;
	mblk_t *np;
	if (!(np = sl_data(q, msg)))
		return (-ENOBUFS);
	if ((err = m2ua_as_read(q, np)))
		return (err);
	return (0);
}

/*
 *  M_PROTO, M_PCPROTO Processing
 *  -------------------------------------------------------------------------
 */
static int ss7_w_proto(queue_t * q, mblk_t * msg)
{
	int prim = *((long *) msg->b_wptr);
	if (SL_DSTR_FIRST <= prim && prim <= SL_DSTR_LAST && sl_prim[prim])
		return (*sl_prim[prim]) (q, msg);
	return (-EOPNOTSUPP);
}

int ss7_r_proto(queue_t * q, mblk_t * msg)
{
	int prim = *((long *) msg->b_rptr);
	if (SL_USTR_FIRST <= prim && prim <= SL_USTR_LAST && sl_prim[prim])
		return ((*sl_prim[prim]) (q, msg));
	return (-EOPNOTSUPP);
}


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

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

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