#include "./include/mtp3.h"
#include "./include/mtpstm.h"
#include "./include/mtpext.h"
#include "./include/mtpfunc.h"
#include "./include/mtp3lite.h"
#include "../../public/src/include/pub_netcap.h"

/*@ignore@*/
extern int mtp3_send_netcap;
#ifndef _M3UA_
#define _M3UA_
#endif
iprt1			mtp3_iprt;
#ifdef _INCLUDE_M2UA
	static m2ua_up_msg_t	*mtp3_m2ua_msg;
#endif
#ifdef _M3UA_
	static xua_up_msg_t	*mtp3_m3ua_msg;
#endif
extern tup_shm			*T_shm_ptr;
extern isup_shm			*I_shm_ptr;
extern bicc_shm			*B_shm_ptr;
extern sccp_shm			*S_shm_ptr;
ulong					msgSourceIP;
extern primitive_to_isup	*I_primitive;
extern primitive_to_bicc	*B_primitive;
extern primitive_to_sccp	*S_primitive;
extern primitive_to_tup		*T_primitive;
extern mtp3_routing_result	routingResult;
extern void mtp3_debug(int n,const char *fmt,...);
extern BYTE mtp3_check_dpc_equal_to_opc(BYTE nw, ulong dpc);

static int detail_debug_flag=0;
static int rc_timer=190;
extern DWORD	mtp_local_ip, mtp_peer_ip;

void tsrc_fun5(WORD linkset);
void stop_mtp3T21(WORD linkset);
BOOL Alinkset_status(BYTE	routine);
BOOL Nlinkset_status(BYTE	routine);
void send_to_host_mtp3(BYTE *msgptr,ulong dst_ip);
int MTP3_LinkIP_List(ulong IP,BYTE mode);
void sp_unaccessable(BYTE *routine);
void mark_normal_linkset_available(BYTE *routine);
void mark_normal_linkset_unavailable(BYTE *routine);
void mark_alternative_linkset_unavailable(BYTE * routine);
void mark_alternative_linkset_available(BYTE * routine);
void mark_dstSP_inaccessible(BYTE *routine);
BYTE get_route_value(u32 dpc, u8 nw, u32 opc);
int send_route_to_other_plat(u32 dpc, BYTE nw, BYTE routine, long dest_ip, WORD chl, u32 opc);
int update_route_by_other_plat(u32 dpc,BYTE nw, BYTE routine, WORD chl, u32 opc);
int scan_ls_link_available(WORD ls_no);
int find_rc_dst_place(DWORD rc, WORD lsno);
int send_command_to_m3ua(WORD link, BYTE command, BYTE xua_msg_class, DWORD rc, DWORD aff_pc);
extern int m2ua_get_traffic_mode_type();

void primitive_to_userpart(BYTE nw,long	dst,BYTE state)
{
	BYTE	I_WSub;
	BYTE	B_WSub;
	BYTE	S_WSub;
	BYTE	T_WSub;
	mtp_primitive	*I_ptr;
	mtp_primitive	*B_ptr;
	mtp_primitive	*S_ptr;
	mtp_primitive	*T_ptr;

	I_WSub = I_primitive->WSub;
	B_WSub = B_primitive->WSub;
	S_WSub = S_primitive->WSub;
	T_WSub = T_primitive->WSub;
	I_ptr = &I_primitive->primitive[I_WSub];
	B_ptr = &B_primitive->primitive[I_WSub];
	S_ptr = &S_primitive->primitive[I_WSub];
	T_ptr = &T_primitive->primitive[I_WSub];

	I_ptr->pc = dst;
	I_ptr->nw_indicator = nw;
	I_ptr->availability = state;

	B_ptr->pc = dst;
	B_ptr->nw_indicator = nw;
	B_ptr->availability = state;

	S_ptr->pc = dst;
	S_ptr->nw_indicator = nw;
	S_ptr->availability = state;

	T_ptr->pc = dst;
	T_ptr->nw_indicator = nw;
	T_ptr->availability = state;

	I_primitive->WSub = (I_WSub + 1) & 0x0f;
	B_primitive->WSub = (I_WSub + 1) & 0x0f;
	S_primitive->WSub = (S_WSub + 1) & 0x0f;
	T_primitive->WSub = (T_WSub + 1) & 0x0f;
}

BYTE *spc_to_acn(BYTE netID,ulong spc)//??-
{
	nw_para	*nw;
	ulong	index;
	mtp3DPCIndex	*sort_rec = &mtp3SortRoutine.nw[netID];
	ull opc_dpc=0;

	netID = netID % 4;
	nw = &mtp3_para->nw[netID];

	if (pc_length(netID) == MTP3_24BIT_PC)
	{
		opc_dpc = mtp3_para->nw[netID].opc24;
		opc_dpc = (opc_dpc<<32) | spc;
		if (nw->opc24 == spc)
			return mtp3_para->nw[netID].local_acn;
	}
	else
	{
		opc_dpc = mtp3_para->nw[netID].opc14;
		opc_dpc = (opc_dpc<<32) | spc;	
		if (nw->opc14 == spc)
			return mtp3_para->nw[netID].local_acn;
	}


	index = Mtp3BinSearchValue(0,sort_rec->sortedNum-1,netID,spc);//??-
	if (index>=0 && index<MAX_ROUTE)
		return nw->routing[sort_rec->index[index]].acn;
	return NULL;
}

BYTE mtp3_ansiFlag(BYTE netID)
{
	netID = netID & 3;
	return (mtp3_para->nw[netID].pc_type) & 1;
}

int	search_outbound_coLink(WORD chl)/* find outbound changeover link */
{
	ls_info		*ls;
	int			i;
	int			lsx16;
	WORD		adsp_place;
	BYTE		nw;
	int			outls;
	int			outlink;
	int			lsno;

	lsno = mtp3_para->lk[chl].e1_to_linkset;
	ls = &mtp3.ls[lsno];
	lsx16 = lsno << 4;
	if (ls->links_available > 0)
	{
		for (i=0; i<16; i++)
		{
			outlink = ls_slc[lsx16+i];
/*			if ( (mtp3ObjState.link_l3_state[outlink] == AVAILABLE) &&
				 (outlink != chl)					 &&
				 (mtp3ObjState.link_l2_state[outlink] == MTP2_STATE_WORKING) )*/
			if ( (mtp3ObjState.link_l3_state[outlink] == AVAILABLE) &&
				 (outlink != chl)					 )
			{
				return ls_slc[lsx16+i];
			}
		}
		return -1;
	}
	else
	{
		nw = mtp3_para->ls_pro[lsno].nw_id;
		adsp_place = ls->adjacent_sp_place;
		if (adsp_place >= MAX_ROUTE)
			return -1;
		if ( ((mtp3.nw[nw].routine[adsp_place] >> 2) & 3) == 0)/* alternative route available */
		{
			outls = mtp3_para->nw[nw].routing[adsp_place].alternative_ls;
			lsx16 = outls << 4;
			for (i=0; i<16; i++)
			{
				outlink = ls_slc[lsx16+i];
/*				if ( (mtp3ObjState.link_l3_state[outlink] == AVAILABLE) &&
					 (mtp3ObjState.link_l2_state[outlink] == MTP2_STATE_WORKING)   )*/
				if ( (mtp3ObjState.link_l3_state[outlink] == AVAILABLE) )
				{
					mtp3_debug(MTP3DB_EVENT,"outlink is %d",outlink);
					return outlink;
				}
			}
			return -1;
		}
	}
	return -1;
}

int pc_length(BYTE	nw)
{
	if (((mtp3_para->nw[nw].pc_len) & 1) == 1)
		return MTP3_24BIT_PC;
	else
		return MTP3_14BIT_PC;
}

void	send_to_mtp2(long dest_ip)// send to 8ke1 care
{
   	mtp3_iprt.io_msg.msgSrcPort = 4950;
	mtp3_iprt.io_msg.msgDstPort = 4950;
	mtp3_iprt.io_msg.msgDstIP = dest_ip;
//	iptrPutMessage(mtp3_iprt.io_msg);
	{//delete one byte of len
//		BYTE tmp[300];
		mtp3_iprt.io_msg.msgLength = mtp3_iprt.io_msg.msgContent[3]+2;
		mtp3_iprt.io_msg.msgContent[0] = mtp3_iprt.io_msg.msgContent[0];//link
		memcpy(&mtp3_iprt.io_msg.msgContent[1], &mtp3_iprt.io_msg.msgContent[3], mtp3_iprt.io_msg.msgContent[2]+1);
//		memcpy(&mtp3_iprt.io_msg.msgContent[0], tmp, tmp[1]+2);
	}
	iptrDirectSendMsg(mtp3_iprt.io_msg);
}

void	send_to_mtp2_new_struct(long dest_ip)//link_high,link_low,len_high,len_low,sio...
{
   	mtp3_iprt.io_msg.msgSrcPort = 4950;
	mtp3_iprt.io_msg.msgDstPort = 4950;
	mtp3_iprt.io_msg.msgDstIP = dest_ip;

	mtp3_iprt.io_msg.msgLength = (mtp3_iprt.io_msg.msgContent[2]<<8) + mtp3_iprt.io_msg.msgContent[3]+3+1;
	if(mtp3_iprt.io_msg.msgLength >MAX_SS7_MSG_LEN)
	{
		mtp3_debug(MTP3DB_ERROR,"Send message in SS7 port 4950, length longer than 300, len=%d!", mtp3_iprt.io_msg.msgLength);
		return;
	}
	iptrDirectSendMsg(mtp3_iprt.io_msg);
}
#ifndef _M3UA_
void send_mtp_msg(int outlink, BYTE	*msgptr)
{
	int		linkset;
	ls_info	*ls;
	ls_para *ls_pro;
	BYTE	nw;
	ulong	dst_ip;
	long	opc;
	long	route_mark;
	BYTE	sls;
	BYTE	pclen;
	WORD len;
	BYTE	ssf;
	BYTE	debugtype=0;

	if(msgptr == NULL)
	{
		return;
	}
	ssf = msgptr[3] & 0x0f;
	linkset = mtp3_para->lk[outlink].e1_to_linkset;
	ls = &mtp3.ls[linkset];
	ls_pro = &mtp3_para->ls_pro[linkset];
	nw = ls_pro->nw_id;
	pclen = pc_length(nw);
	if ( (ls_pro->loopback_opt) != 0 )/* this linkset is loop back linkset */
	{
		if ( pclen == MTP3_24BIT_PC )
		{
			opc = mtp3_para->nw[nw].opc24;
			memcpy( &msgptr[3],&opc,3);/* change msg's dpc to opc */
		}
		else
		{
			opc = mtp3_para->nw[nw].opc14;
			memcpy( (BYTE*)&route_mark,&msgptr[3],4);
			sls = (route_mark >> 28) & 0xf;
			route_mark = (sls << 28)+(opc << 14)+opc;
			memcpy(&msgptr[3],&route_mark,4);
		}
	}

	if (ssf > 1)
	{
		ssf--;
		debugtype = MTP_MSG_DOWN;
	}
	else
		debugtype = MTP_SNM_MSG;
//	current_measure->tf_measure1[4][wx5[nw]+ssf]+=len;/* octets */
	current_measure->tf_measure2[4][wx5[nw]+ssf]++;/* MSUs */

//	len = msgptr[1]+2;
	len = (msgptr[1]<<8) + msgptr[2]+3;
	if(len > MAX_SS7_MSG_LEN)
	{
		mtp3_debug(MTP3DB_ERROR,"send_mtp_msg, length longer than 300, len=%d!", len);
		msgptr[1] = 0;
		len = MAX_SS7_MSG_LEN;
	}
	mtp3_iprt.io_msg.msgLength = len;

	if( mtp3_send_netcap && ( ( msgptr[3] & 0xF0) != 0xF0 ) )
	{
	    int pclen;
	    BYTE sio;
	    BYTE nw;

	    sio = msgptr[3];
	    nw = sio >> 6;
	    pclen = pc_length(nw);

	    if ( pclen == MTP3_24BIT_PC )      //ansi
	    {
	         NcMtp3Send ( &msgptr[3], (msgptr[1]<<8) + msgptr[2], 1 );
	    }
	    else if ( pclen == MTP3_14BIT_PC ) //ITU
	    {
	      	 NcMtp3Send ( &msgptr[3], (msgptr[1]<<8) + msgptr[2], 0 );
	    }
	}

#if _INCLUDE_M2UA
	if (mtp3ObjState.lk_mtp3[outlink] != mtp3_localip)
	{//transfer to remote plat
		dst_ip = mtp3ObjState.lk_mtp3[outlink];
		//dst_ip = (dst_ip << 16) | E1CARD_BASE_IP;
	/* debug show message */
		if (iptrans_msg_flow(msgptr,pclen,debugtype,dst_ip));
	/* debug show message */
//		send_to_mtp2(dst_ip);
		send_to_mtp2_new_struct(dst_ip);
	}
	else if (MTP3_LINK_TYPE(outlink) == LKTYPE_NONE_SIGTRAN)
#endif
	{
		dst_ip = LINK_TO_IP(outlink);
	/* debug show message */
		if (iptrans_msg_flow(msgptr,pclen,debugtype,dst_ip));
	/* debug show message */
		send_to_mtp2(dst_ip);//use old struct send to 8k bload
	}
#if _INCLUDE_M2UA
	else
	{
		if (MTP3_LINK_TYPE(outlink) == LKTYPE_MTP3_LITE)
		{
			/* debug show message */
			dst_ip = mtp3_para->lk[outlink].remote_ip;
			if (iptrans_msg_flow(msgptr,pclen,debugtype,dst_ip));
			/* debug show message */
			if ((msgptr[4] & 0x0f) == 3)
				put_mtp3lite_msg(msgptr);
			return;
		}
		else
		{
			dst_ip = mtp3_para->sg[mtp3_para->lk[outlink].e1_to_sg].ip;
			/* debug show message */
			if (iptrans_msg_flow(msgptr,pclen,debugtype,dst_ip));
			/* debug show message */
			put_m2ua_msg((m2ua_up_msg_t *)msgptr);
			return;
		}
	}
#endif


}
#endif
int check_snmmsg_route(WORD ls)
{
	WORD	sp_place;
	BYTE	nw;
	BYTE	routine;
	WORD	outbound_ls=MAX_LS;
	int		outlink=MAX_LK_INDEX;
	int		lsx16;
	int		i;

	if (mtp3.ls[ls].links_available_t > 0)
	{
		outbound_ls = ls;
	}
	else
	{
		sp_place = mtp3.ls[ls].adjacent_sp_place;
		if (sp_place >= MAX_ROUTE)
			return -1;
		nw = mtp3_para->ls_pro[ls].nw_id;
		routine = mtp3.nw[nw].routine[sp_place];
		if ( (routine & 3) == NLS_AVAILABLE )
			outbound_ls = mtp3_para->nw[nw].routing[sp_place].normal_ls;
		else if ( ((routine >> 2) & 3) == ALS_AVAILABLE )
			outbound_ls = mtp3_para->nw[nw].routing[sp_place].alternative_ls;
		else
		{
//			mtp3_debug(MTP3DB_ERROR,"ls %d Can't find Outbound LS TO LS-Remote PC when SNM\n\r",ls);
			return -1;
		}
	}
	lsx16 = outbound_ls << 4;
	for (i=0; i<16; i++)
	{
		outlink = ls_slc[lsx16+i];
		if ( mtp3ObjState.link_l3_state[outlink] == AVAILABLE )
		{
			return outlink;
		}
		else if (mtp3ObjState.link_l2_state[outlink] == MTP2_STATE_WORKING)
		{
			if (changeback_in_progress[outlink] == TRUE)
			{
				return outlink;
			}
		}
	}
	return -1;
}

void hmrt_srm_msg(WORD linkset, BYTE MsgType, long dst)
{
	ls_info			*ls;
	BYTE			nw;
	long			route_mark;
	BYTE			*sd_tmp_buf;
	int				outlink;

	if (linkset >= MAX_LS)
		return;
	if (dst == mtp3_para->ls_pro[linkset].ls_op_pc)
		return;
	outlink = check_snmmsg_route(linkset);
	if (outlink == -1)
		return;
	ls = &mtp3.ls[linkset];
	nw = mtp3_para->ls_pro[linkset].nw_id;

	sd_tmp_buf = &mtp3_iprt.io_msg.msgContent[0];
	if ( pc_length(nw) == MTP3_24BIT_PC )
	{
		sd_tmp_buf[2] = 0;
		sd_tmp_buf[3] = 12;
		sd_tmp_buf[4] = nw << 6;
		memcpy(&sd_tmp_buf[5],&mtp3_para->ls_pro[linkset].ls_op_pc,3);
		//memcpy(&sd_tmp_buf[7],&mtp3_para->nw[nw].opc24,3);
		if(mtp3_para->ls_pro[linkset].ls_opc==0)
			memcpy(&sd_tmp_buf[8],&mtp3_para->nw[nw].opc24,3);
		else 
			memcpy(&sd_tmp_buf[8],&mtp3_para->ls_pro[linkset].ls_opc,3);
		sd_tmp_buf[11] = 0;
		sd_tmp_buf[12] = MsgType;
		memcpy(&sd_tmp_buf[13],&dst,3);
	}
	else
	{
		if(mtp3_para->ls_pro[linkset].ls_opc==0)
			route_mark = (mtp3_para->nw[nw].opc14 << 14) + mtp3_para->ls_pro[linkset].ls_op_pc;
		else
			route_mark = (mtp3_para->ls_pro[linkset].ls_opc << 14) + mtp3_para->ls_pro[linkset].ls_op_pc;
		sd_tmp_buf[2] = 0;
		sd_tmp_buf[3] = 8;
		sd_tmp_buf[4] = nw << 6;
		memcpy(&sd_tmp_buf[5],&route_mark,4);
		sd_tmp_buf[9] = MsgType;
		memcpy(&sd_tmp_buf[10],&dst,2);
	}
	sd_tmp_buf[1] = outlink>>8;
	sd_tmp_buf[0] = outlink & 0xff;
	send_mtp_msg(outlink,sd_tmp_buf);
}

int priority_own_link(WORD lsno,WORD sls)
{
	ls_info	*ls;
	int		i;
	WORD	link;

	if (lsno >= MAX_LS_NUM)
		return -1;

	ls = &mtp3.ls[lsno];

	if(detail_debug_flag)
	{
		if(1)
		{
			char buf[256];
			char strbuf[1024];
			
			mtp3_debug(MTP3DB_EVENT, "%s, linkset=%d, sls=%d, linkconfigred=%d ",
				__FUNCTION__, 
				lsno, 
				sls,
				mtp3.ls[lsno].linksNum_configured);
			memset(strbuf, 0x00, 16);
			for(i=0;i<2; i++)
			{
				link = ls_sls[(lsno<<4)+i];
				sprintf(buf, "ls_sls[%02d]=%d, ip=%08x, state=%d",
					i,
					ls_sls[(lsno<<4)+i],
					mtp3_para->lk[link].e1_to_mtp3,
					mtp3ObjState.link_l3_state[link]);
				strcat(strbuf, buf);
			}
			mtp3_debug(MTP3DB_EVENT, "%s, %s ",
					__FUNCTION__, 
					strbuf);			
		}
	}
	
	for (i=0;i<16;i++)
//	for (i=0;i<mtp3.ls[lsno].linksNum_configured;i++)
	{
		link = ls_sls[(lsno<<4)+i];
		if (mtp3_para->lk[link].e1_to_mtp3 == mtp3_localip && mtp3ObjState.link_l3_state[link] == AVAILABLE)
			return link;
	}
	
	for (i=0;i<16;i++)
//	for (i=0;i<mtp3.ls[lsno].linksNum_configured;i++)
	{
		link = ls_sls[(lsno<<4)+i];
				
		if ( mtp3ObjState.link_l3_state[link] == AVAILABLE)
			return link;
	}
	
	return ls_sls[(lsno<<4)+(sls & 15)];
}

int get_asp_ac_link(WORD lsno,WORD sls)
{
	ls_info	*ls;
	int		i;
	WORD	link;

	if (lsno >= MAX_LS_NUM)
		return -1;

	ls = &mtp3.ls[lsno];
	for (i=0;i<mtp3.ls[lsno].linksNum_configured;i++)
	{
		link = ls_sls[(lsno<<4)+i];
		if(ls->send_asp_ac_link_id == link)
			return link;
	}
	
	for (i=0;i<mtp3.ls[lsno].linksNum_configured;i++)
	{
		link = ls_sls[(lsno<<4)+i];
		if (mtp3_para->lk[link].e1_to_mtp3 != mtp3_localip && mtp3ObjState.link_l3_state[link] == AVAILABLE)
			return link;
	}

	for (i=0;i<mtp3.ls[lsno].linksNum_configured;i++)
	{
		link = ls_sls[(lsno<<4)+i];
		if (mtp3_para->lk[link].e1_to_mtp3 == mtp3_localip && mtp3ObjState.link_l3_state[link] == AVAILABLE)
			return link;
	}
	
	return ls_sls[(lsno<<4)+(sls & 15)];
}

int	check_outbound_route(BYTE nw, long dpc, WORD sls, long opc)
{
	network	*sp;
	BYTE	outroute;
	WORD	ls;
	WORD	i;
	BYTE	routine;
	WORD	nls;
	mtp3DPCIndex	*sort_rec = &mtp3SortRoutine.nw[nw];
	int		index;
	WORD	outlink;
	ull opc_dpc=0;

	ls_info	*ls_info;

	if (dpc==0)
		return -3;

	sp = &mtp3.nw[nw];
	if(opc == mtp3_para->nw[nw].opc14)
	{
		opc =0;
	}
	opc_dpc = opc;
	opc_dpc = (opc_dpc <<32)|dpc;
	index = Mtp3BinSearchValue(0,sort_rec->sortedNum-1,nw,opc_dpc);
	if ((index >= 0) && (index < MAX_ROUTE))
		i = sort_rec->index[index];
	else
		return -3;

	routine = sp->routine[i];
	outroute =  (routine >> 6) & 3;
	if ( outroute == 2 )/* no outbound route */
	{
		nls = mtp3_para->nw[nw].routing[i].normal_ls;
		if (mtp3.ls[nls].linksNum_configured > 0)
//		if (linknum_in_ls[nls] > 0)
			return -1;
		else
			return -2;
	}
	else if ( (outroute == 0) &&
			  ((routine & 3) == NLS_AVAILABLE)	)/* current route is normal route */
	{
		ls = mtp3_para->nw[nw].routing[i].normal_ls;
		outlink = ls_sls[(ls<<4)+sls];

		ls_info = &mtp3.ls[ls];

		/* added for override link status -- start */
		/*
		if(m2ua_get_traffic_mode_type()==0)
		{	
			if(ls_info->send_asp_ac_link_id>0 && ls_info->send_asp_ac_link_id != 0xffff)
			{
	
				return ls_info->send_asp_ac_link_id;
			}
			//if(ls_info->send_asp_ac_link_id != outlink)
			{
				int link_no = get_asp_ac_link(ls,sls);

	
				return link_no;			
			}
		}		
		*/
		/* added for override link status  -- end*/
		
		if (mtp3_para->lk[outlink].e1_to_mtp3 == mtp3_localip && mtp3ObjState.link_l3_state[outlink] == AVAILABLE)
			return outlink;
		else
			return priority_own_link(ls,sls);
	}
	else if ( ((routine >> 2) & 3) == ALS_AVAILABLE)
	{
		ls = mtp3_para->nw[nw].routing[i].alternative_ls;
		outlink = ls_sls[(ls<<4)+sls];

		ls_info = &mtp3.ls[ls];

		/* added for override link status -- start */
		/*
		if(m2ua_get_traffic_mode_type()==0)
		{	
			if(ls_info->send_asp_ac_link_id>0 && ls_info->send_asp_ac_link_id != 0xffff)
			{
	
				return ls_info->send_asp_ac_link_id;
			}
			//if(ls_info->send_asp_ac_link_id != outlink)
			{
				int link_no = get_asp_ac_link(ls,sls);

	
				return link_no;			
			}
		}	
		*/
		/* added for override link status  -- end*/

		if (mtp3_para->lk[outlink].e1_to_mtp3 == mtp3_localip && mtp3ObjState.link_l3_state[outlink] == AVAILABLE)
			return outlink;
		else
			return priority_own_link(ls,sls);
	}
	else
	{
	       ls = mtp3_para->nw[nw].routing[i].alternative_ls;
		outlink = ls_sls[(ls<<4)+sls];

		ls_info = &mtp3.ls[ls];

	    if(mtp3_para->ls_pro[ls].ls_state == 1)
	    {
	        if (mtp3_para->lk[outlink].e1_to_mtp3 == mtp3_localip && mtp3ObjState.link_l3_state[outlink] == AVAILABLE)
			return outlink;
		else
			return priority_own_link(ls,sls);
	    }
	}
	
	return -3;
}

/* pc_length:point code type
 * ss7 network has two kind of point code,one is 14bits length,
 * another is 24bits length */

int	send_to_sccp(BYTE *msgptr)/* send sccp msg to tele user part */
{
	up_message *ToSccp;
	WORD		len;
	long		route_mark;/* route mark */
	BYTE		pclen;
	BYTE		nw;
	BYTE		sio;
	WORD		link;

	sio = msgptr[4];
	nw = sio >> 6;
	sio = sio & 0xEF;//init spare bit
	sio = sio | (mtp3_ansiFlag(nw) << 4);
   	ToSccp = &S_shm_ptr->MS_Buf.msgNum[S_shm_ptr->MS_Buf.WSub];
	link = msgptr[1]*256+msgptr[0];
	ToSccp->link = link;
	ToSccp->dest_ip = msgSourceIP;

	pclen = pc_length(nw);
	if (pclen == MTP3_24BIT_PC)/* for 24bit ss7 network */
   	{
   		if (msgptr[2] == 0 && msgptr[3] < 9)//len < 9
   		{
   			mtp3ObjState.MTP3WatchDog[3]++;
   			mtp3.nw[nw].flow.MtoU_throwed[0]++;
			mtp3_debug(MTP3DB_ERROR,"[SCCP]MTP3<==MTP2,LI over range and discarded! LI=%02d,Link=%d",msgptr[3],link);
   			return 0;
   		}

		memcpy((BYTE *)&ToSccp->dpc,msgptr+5,3);/* message's dpc */
		memcpy((BYTE *)&ToSccp->opc,&msgptr[8],3);/* message's opc */
   		ToSccp->sio = sio;
   		ToSccp->cic[0] = msgptr[11];
   		len = (msgptr[2]<<8) + msgptr[3]-8;
   		ToSccp->len = len;
   		memcpy(&ToSccp->msgList,&msgptr[12],len);
   	}
   	else
   	{
   		if (msgptr[2] == 0 && msgptr[3] < 6)
   		{
   			mtp3ObjState.MTP3WatchDog[4]++;
   			mtp3.nw[nw].flow.MtoU_throwed[0]++;
			mtp3_debug(MTP3DB_ERROR,"[SCCP]MTP3<==MTP2,LI over range and discarded! LI=%02d,Link=%d",msgptr[3],link);
   			return 0;
   		}

		memcpy((BYTE*)&route_mark,&msgptr[5],4);/* include message's dpc,opc,sls */
		ToSccp->cic[0] = (route_mark >> 28) & 0xf;
		ToSccp->opc = (route_mark & 0x0FFFFFFF) >> 14;
		ToSccp->dpc = (route_mark & 0x3FFF);
   		ToSccp->sio = sio;
   		len = (msgptr[2]<<8) + msgptr[3] -5;
   		ToSccp->len = len;
   		memcpy(&ToSccp->msgList,&msgptr[9],len);
   	}
	S_shm_ptr->MS_Buf.WSub ++;
	mtp3.nw[nw].flow.MtoU[2]++;
	return 1;
}

int	send_to_sccp_lite(up_message *msgptr)/* send sccp-lite msg to sccp */
{
	up_message *ToSccp;
	BYTE 		nw;

	nw = msgptr->sio >> 6;

   	ToSccp = &S_shm_ptr->MS_Buf.msgNum[S_shm_ptr->MS_Buf.WSub];
	memcpy((BYTE *)ToSccp, (BYTE *)msgptr, sizeof(up_message));

	S_shm_ptr->MS_Buf.WSub ++;
	mtp3.nw[nw].flow.MtoU[2]++;

	return 1;
}

int	send_to_tup(BYTE *msgptr)/* send tup msg to tele user part */
{
	BYTE 		sio;
	WORD		len;
	up_message	*ToTup;
	long		route_mark;
	BYTE		pclen;
	BYTE		nw;
	WORD		link;

	sio = msgptr[4];

	nw = sio >> 6;
	sio = sio & 0xEF;//init spare bit	
	sio = sio | (mtp3_ansiFlag(nw) << 4);
	link = msgptr[1]*256+msgptr[0];	
	pclen = pc_length(nw);
	ToTup = &T_shm_ptr->MT_Buf.msgNum[T_shm_ptr->MT_Buf.WSub];
	ToTup->link = link;
	ToTup->dest_ip = msgSourceIP;

	if (pclen == MTP3_24BIT_PC)/* for 24bits network */
	{
   		if (msgptr[2] == 0 && msgptr[3] < 10)
   		{
   			mtp3ObjState.MTP3WatchDog[5]++;
   			mtp3.nw[nw].flow.MtoU_throwed[1]++;
			mtp3_debug(MTP3DB_ERROR,"[TUP]MTP3<==MTP2,LI over range and discarded! LI=%02d,Link=%d",msgptr[3],link);
   			return 0;
   		}

		ToTup->sio = sio;
		memcpy((BYTE*)&ToTup->dpc,&msgptr[5],3);/* message's dpc */
		memcpy((BYTE*)&ToTup->opc,&msgptr[8],3);/* message's opc */
		ToTup->cic[0] = msgptr[11];
		ToTup->cic[1] = msgptr[12];
		len = (msgptr[2]<<8) + msgptr[3] -9;
		ToTup->len = len;
		memcpy(&ToTup->msgList,&msgptr[13],len);
	}
	else/* for 14bits network */
	{
   		if (msgptr[2] == 0 && msgptr[3] < 7)
   		{
   			mtp3ObjState.MTP3WatchDog[6]++;
   			mtp3.nw[nw].flow.MtoU_throwed[1]++;
			mtp3_debug(MTP3DB_ERROR,"[TUP]MTP3<==MTP2,LI over range and discarded! LI=%02d,Link=%d",msgptr[3],link);
   			return 0;
   		}

		memcpy((BYTE*)&route_mark,&msgptr[5],4);/* include message's dpc,opc,sls */
		ToTup->opc = (route_mark & 0x0FFFFFFF) >> 14;
		ToTup->dpc = (route_mark & 0x3FFF);
		ToTup->cic[0] = (msgptr[8] >> 4) + ((msgptr[9] & 0x0f) << 4);
		ToTup->cic[1] = (msgptr[9] >> 4);
		ToTup->sio = sio;
		len =  (msgptr[2]<<8) + msgptr[3] - 6;
		ToTup->len = len;
		memcpy(&ToTup->msgList,&msgptr[10],len);
	}
	T_shm_ptr->MT_Buf.WSub ++;
	mtp3.nw[nw].flow.MtoU[3]++;
	return 1;
}

void MTP3_recv_isup_count(BYTE nw,BYTE type)
{
	switch (type)
	{
		case MTP3_ISUP_IAM:
			mtp3.nw[nw].flow.isup_detail[0]++;
			break;
		case MTP3_ISUP_ACM:
			mtp3.nw[nw].flow.isup_detail[1]++;
			break;
		case MTP3_ISUP_CPG:
			mtp3.nw[nw].flow.isup_detail[2]++;
			break;
		case MTP3_ISUP_ANM:
			mtp3.nw[nw].flow.isup_detail[3]++;
			break;
		case MTP3_ISUP_REL:
			mtp3.nw[nw].flow.isup_detail[4]++;
			break;
		case MTP3_ISUP_RLC:
			mtp3.nw[nw].flow.isup_detail[5]++;
			break;
		default:
			break;
	}
}

int	send_to_isup(BYTE *msgptr)/* send isup msg to tele user part */
{
	BYTE		sio;
	WORD 		len;
	up_message *ToIsup;
	long		route_mark;
	BYTE		pclen;
	BYTE		nw;
	WORD		link;

	sio = msgptr[4];
	nw = sio >> 6;
	sio = sio & 0xEF;//init spare bit	
	sio = sio | (mtp3_ansiFlag(nw) << 4);
	ToIsup = &I_shm_ptr->MI_Buf.msgNum[I_shm_ptr->MI_Buf.WSub];
	pclen = pc_length(nw);
	link = msgptr[1]*256+msgptr[0];
	ToIsup->link = link;
	ToIsup->dest_ip = msgSourceIP;
	if (pclen == MTP3_24BIT_PC)/* for 24bit ss7 network */
	{
   		if (msgptr[2] == 0 && msgptr[3] < 11)
   		{
   			mtp3ObjState.MTP3WatchDog[7]++;
   			mtp3.nw[nw].flow.MtoU_throwed[2]++;
			mtp3_debug(MTP3DB_ERROR,"[ISUP]MTP3<==MTP2,LI over range and discarded! LI=%02d,Link=%d",msgptr[3],link);
   			return 0;
   		}

		memcpy((BYTE*)&ToIsup->dpc,&msgptr[5],3);
		memcpy((BYTE*)&ToIsup->opc,&msgptr[8],3);
		ToIsup->sio = sio;
		ToIsup->cic[0] = msgptr[12];
		ToIsup->cic[1] = msgptr[13];
		len = (msgptr[2]<<8) + msgptr[3] -10;
		ToIsup->len = len;
		memcpy(&ToIsup->msgList,&msgptr[14],len);
		MTP3_recv_isup_count(nw,msgptr[14]);
	}
	else/* for 14bit ss7 network */
	{
   		if (msgptr[2] == 0 && msgptr[3] < 8)
   		{
   			mtp3ObjState.MTP3WatchDog[8]++;
   			mtp3.nw[nw].flow.MtoU_throwed[2]++;
			mtp3_debug(MTP3DB_ERROR,"[ISUP]MTP3<==MTP2,LI over range and discarded! LI=%02d,Link=%d",msgptr[3],link);
   			return 0;
   		}

		memcpy((BYTE*)&route_mark,&msgptr[5],4);/* include message's dpc,opc,sls */
		ToIsup->opc = (route_mark & 0x0FFFFFFF) >> 14;
		ToIsup->dpc = (route_mark & 0x3FFF);
		ToIsup->sio = sio;
		ToIsup->cic[0] = msgptr[9];
		ToIsup->cic[1] = msgptr[10];
		len = (msgptr[2]<<8) + msgptr[3] -7;
		ToIsup->len = len;
		memcpy(&ToIsup->msgList,&msgptr[11],len);
		MTP3_recv_isup_count(nw,msgptr[11]);
	}
	I_shm_ptr->MI_Buf.WSub ++;
	mtp3.nw[nw].flow.MtoU[4]++;
	return 1;
}

int	send_to_bicc(BYTE *msgptr)/* send isup msg to tele user part */
{
	BYTE			sio;
	WORD 			len;
	up_message_2 	*ToBicc;
	long			route_mark;
	BYTE			pclen;
	BYTE			nw;
	WORD			link;

	sio = msgptr[4];
	nw = sio >> 6;
	sio = sio & 0xEF;//init spare bit	
	sio = sio | (mtp3_ansiFlag(nw) << 4);
	ToBicc = &B_shm_ptr->MI_Buf.msgNum[B_shm_ptr->MI_Buf.WSub];
	pclen = pc_length(nw);
	link = msgptr[1]*256+msgptr[0];
	ToBicc->link = link;
	ToBicc->dest_ip = msgSourceIP;
	if (pclen == MTP3_24BIT_PC)/* for 24bit ss7 network */
	{
		memcpy((BYTE*)&ToBicc->dpc,&msgptr[5],3);
		memcpy((BYTE*)&ToBicc->opc,&msgptr[8],3);
		ToBicc->sio = sio;
		ToBicc->cic[0] = msgptr[12];
		ToBicc->cic[1] = msgptr[13];
		ToBicc->cic[2] = msgptr[14];
		ToBicc->cic[3] = msgptr[15];
		len = (msgptr[2]<<8) + msgptr[3] -12;
		ToBicc->len = len;
		memcpy(&ToBicc->msgList,&msgptr[16],len);
	}
	else/* for 14bit ss7 network */
	{
		memcpy((BYTE*)&route_mark,&msgptr[5],4);/* include message's dpc,opc,sls */
		ToBicc->opc = (route_mark & 0x0FFFFFFF) >> 14;
		ToBicc->dpc = (route_mark & 0x3FFF);
		ToBicc->sio = sio;
		ToBicc->cic[0] = msgptr[9];
		ToBicc->cic[1] = msgptr[10];
		ToBicc->cic[2] = msgptr[11];
		ToBicc->cic[3] = msgptr[12];
		len = (msgptr[2]<<8) + msgptr[3] -9;
		ToBicc->len = len;
		memcpy(&ToBicc->msgList,&msgptr[13],len);
	}
	B_shm_ptr->MI_Buf.WSub ++;
	mtp3.nw[nw].flow.MtoU[4]++;
	return 1;
}

int get_sccp(up_message *GetSccp)
{
	WORD 	len;
	BYTE	sio;
	long	route_mark;/* dpc opc sls */
	BYTE	sls;
	long	dpc;
	BYTE	pclen;
	int		outlink=0;
	long	dest_ip;
	BYTE	*msgptr;
	BYTE	nw;
	BYTE	rSub;

	rSub = S_shm_ptr->SM_Buf.RSub;
	if (rSub != S_shm_ptr->SM_Buf.WSub)
	{
		GetSccp = &S_shm_ptr->SM_Buf.msgNum[rSub];
		sio = GetSccp->sio & 0xcf;
		dpc = GetSccp->dpc;
		sls = GetSccp->cic[0] & 0x0f;
		nw = (sio >> 6) & 3;
		pclen = pc_length(nw);
		len = GetSccp->len;

		dest_ip = GetSccp->dest_ip;
		if (dest_ip == 0xffffffff)
		{
			outlink = routingResult.sccpMsgOutLink[rSub];
//			outlink = check_outbound_route(nw,dpc,sls);
			if ( outlink < 0 )
			{
				mtp3_debug(MTP3DB_ERROR,"USER==>MTP3,sio=%x,dpc=%lx",GetSccp->sio,GetSccp->dpc);
				mtp3_showbuf(MTP3DB_ERROR,GetSccp->msgList,GetSccp->len);
				mtp3_debug(MTP3DB_ERROR,"perform routing:Route Failure,Reason:program bug");
				S_shm_ptr->SM_Buf.RSub ++;
				mtp3.nw[nw].flow.MtoI_throwed[2]++;
				return 0;
			}
		}
		else{
			outlink = GetSccp->link;
		}

		msgptr = &mtp3_iprt.io_msg.msgContent[0];
		len = GetSccp->len;
		if (pclen == MTP3_24BIT_PC)
		{
			mtp3_iprt.io_msg.msgLength = len + 10+1+1;
			msgptr[1] = outlink>>8;
			msgptr[0] = outlink&0xff;
			msgptr[2] = (len+8)>>8;
			msgptr[3] = (len+8) & 0xff;
			msgptr[4] = sio;
			memcpy(&msgptr[5],&dpc,3);
			if(GetSccp->opc==0)
				memcpy(&msgptr[8],&mtp3_para->nw[nw].opc24,3);
			else 
				memcpy(&msgptr[8],&GetSccp->opc,3);
			memcpy(&msgptr[11],&GetSccp->cic[0],1);
			memcpy(&msgptr[12],&GetSccp->msgList,len);
		}
		else
		{
			if(GetSccp->opc==0)				
				route_mark = (GetSccp->cic[0] << 28)+(mtp3_para->nw[nw].opc14 << 14)+dpc;
			else 
				route_mark = (GetSccp->cic[0] << 28)+(GetSccp->opc << 14)+dpc;
			msgptr[1] = outlink>>8;
			msgptr[0] = outlink&0xff;
			msgptr[2] = (len+5)>>8;
			msgptr[3] = (len+5) & 0xff;
			msgptr[4] = sio;
			memcpy(&msgptr[5],&route_mark,4);
			memcpy(&msgptr[9],&GetSccp->msgList,len);
		}
		len = (msgptr[2]<<8) | msgptr[3];
//		if ((msgptr[1] < 5) || (msgptr[1] > 0xfd))
		if ((len < 5) || (len > MAX_SS7_MSG_LEN))
		{
			mtp3ObjState.MTP3WatchDog[10]++;
			mtp3_debug(MTP3DB_ERROR,"[SCCP]USER==>MTP3,LI over range and discarded! LI=%04d,Link=%d",len,outlink);
			mtp3_showbuf(MTP3DB_ERROR,&msgptr[0],len + 3+1);
			S_shm_ptr->SM_Buf.RSub ++;
			mtp3.nw[nw].flow.MtoI_throwed[2]++;
			return 0;
		}

		mtp3.nw[nw].flow.MtoI[2]++;
		if (dest_ip == 0xffffffff)
		{
			send_mtp_msg(outlink,msgptr);
		}
		else
		{
			mtp3_iprt.io_msg.msgLength = len + 3+1;
			if (iptrans_msg_flow(msgptr,pclen,MTP_MSG_OTHER_SERVER,dest_ip));
//			send_to_mtp2(dest_ip);
			send_to_mtp2_new_struct(dest_ip);

/*			in.s_addr = dest_ip;
			mtp3_debug(MTP3DB_SCCPMSG,"USER==>MTP3,sio=%x,dpc=%lx",GetSccp->sio,GetSccp->dpc);
			mtp3_debug(MTP3DB_SCCPMSG,"perform routing:%dBIT LI=%x LINK=%x IP=%s",pclen,sio,sls,inet_ntoa(in));
			userpart_msg_flow(msgptr);*/

		}
		S_shm_ptr->SM_Buf.RSub ++;
	}
	return 1;
}

int get_tup(up_message *GetTup)
{
	int 		outlink=0;
	WORD 		len;
	BYTE		sio;
	long		route_mark;
	long		dpc;
	BYTE		sls;
	BYTE		pclen;
	BYTE		*msgptr;
	BYTE		nw;
	ulong		dest_ip;
	BYTE		rSub;

	rSub = T_shm_ptr->TM_Buf.RSub;
	if (rSub != T_shm_ptr->TM_Buf.WSub)
	{

		GetTup = &T_shm_ptr->TM_Buf.msgNum[rSub];
		sio = GetTup->sio & 0xcf;
		dpc = GetTup->dpc;
		sls = GetTup->cic[0] & 0x0f;
		nw = (sio >> 6) & 3;
		pclen = pc_length(nw);
		len = GetTup->len;

		dest_ip = GetTup->dest_ip;
		if (dest_ip == 0xffffffff)
		{
			outlink = routingResult.tupMsgOutLink[rSub];
//			outlink = check_outbound_route(nw,dpc,sls);
			if ( outlink < 0 )
			{
				mtp3_debug(MTP3DB_ERROR,"receive message from UP,sio=%x,dpc=%lx",GetTup->sio,GetTup->dpc);
				mtp3_showbuf(MTP3DB_ERROR,GetTup->msgList,GetTup->len);
				mtp3_debug(MTP3DB_ERROR,"perform routing:Route Failure,Reason:program bug");
				T_shm_ptr->TM_Buf.RSub ++;
				mtp3.nw[nw].flow.MtoI_throwed[3]++;
				return 0;
			}
		}
		else
			outlink = GetTup->link;

		msgptr = &mtp3_iprt.io_msg.msgContent[0];
		if (pclen == MTP3_24BIT_PC)
		{
			msgptr[1] = outlink>>8;
			msgptr[0] = outlink&0xff;
			msgptr[2] = (len+9)>>8;
			msgptr[3] = (len+9) & 0xff;
			msgptr[4] = sio;
			memcpy(&msgptr[5],&dpc,3);

			//memcpy(&msgptr[6],&mtp3_para->nw[nw].opc24,3);

			if (dest_ip == 0xffffffff)
			{
				if (GetTup->opc == 0)
					memcpy(&msgptr[8],&mtp3_para->nw[nw].opc24,3);
				else
					memcpy(&msgptr[8],&GetTup->opc,3);//keep the UP filled opc
			}
			else
				memcpy(&msgptr[8],&GetTup->opc,3);//keep the UP filled opc

			memcpy(&msgptr[11],&GetTup->cic[0],2);
			memcpy(&msgptr[13],&GetTup->msgList,len);
		}
		else
		{
			//route_mark = (GetTup->cic[0] << 28)+(mtp3_para->nw[nw].opc14 << 14)+dpc;

			if (dest_ip == 0xffffffff)
			{
				if (GetTup->opc == 0)
					route_mark = (GetTup->cic[0] << 28)+(mtp3_para->nw[nw].opc14 << 14)+dpc;
				else
					route_mark = (GetTup->cic[0] << 28)+(GetTup->opc << 14)+dpc;//keep the UP filled opc
			}
			else
				route_mark = (GetTup->cic[0] << 28)+(GetTup->opc << 14)+dpc;//keep the UP filled opc

			msgptr[1] = outlink>>8;
			msgptr[0] = outlink&0xff;
			msgptr[2] = (GetTup->len+6)>>8;
			msgptr[3] = (GetTup->len+6) & 0xff;
			msgptr[4] = sio;
			memcpy(&msgptr[5],&route_mark,4);
			msgptr[9] = (GetTup->cic[0] >> 4) + (GetTup->cic[1] << 4);
			memcpy(&msgptr[10],&GetTup->msgList,len);
		}

		len = (msgptr[2]<<8) | msgptr[3];
//		if ((msgptr[1] < 5) || (msgptr[1] > 0xfd))
		if ((len < 5) || (len > MAX_SS7_MSG_LEN))
		{
			mtp3ObjState.MTP3WatchDog[12]++;
			mtp3_debug(MTP3DB_ERROR,"[TUP]USER==>MTP3,LI over range and discarded! LI=%04d,Link=%d",len,outlink);
			mtp3_showbuf(MTP3DB_ERROR,&msgptr[0],len+3+1);
			T_shm_ptr->TM_Buf.RSub ++;
			mtp3.nw[nw].flow.MtoI_throwed[3]++;
			return 0;
		}

		mtp3.nw[nw].flow.MtoI[3]++;
		if (dest_ip == 0xffffffff)
		{
			send_mtp_msg(outlink,msgptr);
		}
		else
		{
			mtp3_iprt.io_msg.msgLength = len+3+1;
			if (iptrans_msg_flow(msgptr,pclen,MTP_MSG_OTHER_SERVER,dest_ip));
//			send_to_mtp2(dest_ip);
			send_to_mtp2_new_struct(dest_ip);
		}
		T_shm_ptr->TM_Buf.RSub ++;
	}
	return 1;
}

void MTP3_send_isup_count(BYTE nw,BYTE type)
{
	switch (type)
	{
		case MTP3_ISUP_IAM:
			mtp3.nw[nw].flow.isup_detail[16]++;
			break;
		case MTP3_ISUP_ACM:
			mtp3.nw[nw].flow.isup_detail[17]++;
			break;
		case MTP3_ISUP_CPG:
			mtp3.nw[nw].flow.isup_detail[18]++;
			break;
		case MTP3_ISUP_ANM:
			mtp3.nw[nw].flow.isup_detail[19]++;
			break;
		case MTP3_ISUP_REL:
			mtp3.nw[nw].flow.isup_detail[20]++;
			break;
		case MTP3_ISUP_RLC:
			mtp3.nw[nw].flow.isup_detail[21]++;
			break;
		default:
			break;
	}
}

int get_isup(up_message *GetIsup)
{
	int 	outlink=0;
	WORD 	len;
	BYTE	sio;
	long	route_mark;
	long	dpc;
	BYTE	sls;
	BYTE	pclen;
	BYTE	*msgptr;
	BYTE	nw;
	ulong	dest_ip;
	BYTE	rSub;

	rSub = I_shm_ptr->IM_Buf.RSub;
	if (rSub != I_shm_ptr->IM_Buf.WSub)
	{

		GetIsup = &I_shm_ptr->IM_Buf.msgNum[rSub];
		sio = GetIsup->sio & 0xcf;
		dpc = GetIsup->dpc;
		sls = GetIsup->cic[0] & 0x0f;
		nw = (sio >> 6) & 3;
		pclen = pc_length(nw);
		len = GetIsup->len;

		dest_ip = GetIsup->dest_ip;
		if (dest_ip == 0xffffffff)
		{
			outlink = routingResult.isupMsgOutLink[rSub];
//			outlink = check_outbound_route(nw,dpc,sls);
			if ( outlink < 0 )
			{
				mtp3_debug(MTP3DB_ERROR,"receive message from UP,sio=%x,dpc=%lx",GetIsup->sio,GetIsup->dpc);
				mtp3_showbuf(MTP3DB_ERROR,GetIsup->msgList,GetIsup->len);
				mtp3_debug(MTP3DB_ERROR,"perform routing:Route Failure,Reason:program bug");
				I_shm_ptr->IM_Buf.RSub ++;
				mtp3.nw[nw].flow.MtoI_throwed[4]++;
				return 0;
			}
		}
		else
			outlink = GetIsup->link;
		msgptr = &mtp3_iprt.io_msg.msgContent[0];
		if (pclen == MTP3_24BIT_PC)
		{
			msgptr[1] = outlink>>8;
			msgptr[0] = outlink&0xff;
			msgptr[2] = (len + 10)/0xff;
			msgptr[3] = (len + 10)&0xff;
			msgptr[4] = sio;
			memcpy(&msgptr[5],&dpc,3);

			if (dest_ip == 0xffffffff)
			{
				if (GetIsup->opc == 0)
					memcpy(&msgptr[8],&mtp3_para->nw[nw].opc24,3);
				else
					memcpy(&msgptr[8],&GetIsup->opc,3);//keep the UP filled opc
			}
			else
				memcpy(&msgptr[8],&GetIsup->opc,3);//keep the UP filled opc

			msgptr[11] = GetIsup->cic[0] & 0x0f;
			memcpy(&msgptr[12],&GetIsup->cic[0],2);
			memcpy(&msgptr[14],&GetIsup->msgList,len);
			MTP3_send_isup_count(nw,msgptr[14]);
		}
		else
		{
			if (dest_ip == 0xffffffff)
			{
				if (GetIsup->opc == 0)
					route_mark = (GetIsup->cic[0] << 28)+(mtp3_para->nw[nw].opc14 << 14)+dpc;
				else
					route_mark = (GetIsup->cic[0] << 28)+(GetIsup->opc << 14)+dpc;//keep the UP filled opc
			}
			else
				route_mark = (GetIsup->cic[0] << 28)+(GetIsup->opc << 14)+dpc;//keep the UP filled opc
			msgptr[1] = outlink>>8;
			msgptr[0] = outlink&0xff;
			msgptr[2] = (len+7)/0xff;
			msgptr[3] = (len+7)&0xff;
			msgptr[4] = sio;
			memcpy(&msgptr[5],&route_mark,4);
			memcpy(&msgptr[9],&GetIsup->cic,2);
			memcpy(&msgptr[11],&GetIsup->msgList,len);
			MTP3_send_isup_count(nw,msgptr[11]);
		}

		len = (msgptr[2]<<8) | msgptr[3];
//		if ((msgptr[1] < 5) || (msgptr[1] > 0xfd))
		if ((len < 5) || (len > MAX_SS7_MSG_LEN))
		{
			mtp3ObjState.MTP3WatchDog[14]++;
			mtp3_debug(MTP3DB_ERROR,"[ISUP]USER==>MTP3,LI over range and discarded! LI=%04d,Link=%d",len,outlink);
			mtp3_showbuf(MTP3DB_ERROR,&msgptr[0],len+3+1);
			I_shm_ptr->IM_Buf.RSub ++;
			mtp3.nw[nw].flow.MtoI_throwed[4]++;
			return 0;
		}

		mtp3.nw[nw].flow.MtoI[4]++;
		if (dest_ip == 0xffffffff)
		{
			send_mtp_msg(outlink,msgptr);
		}
		else
		{
			mtp3_iprt.io_msg.msgLength = len+3+1;
			if (iptrans_msg_flow(msgptr,pclen,MTP_MSG_OTHER_SERVER,dest_ip));
//			send_to_mtp2(dest_ip);
			send_to_mtp2_new_struct(dest_ip);
		}
		I_shm_ptr->IM_Buf.RSub ++;
	}
	return 1;
}

int get_bicc(up_message_2 *GetBicc)
{
	int 	outlink=0;
	WORD 	len;
	BYTE	sio;
	long	route_mark;
	long	dpc;
	BYTE	sls;
	BYTE	pclen;
	BYTE	*msgptr;
	BYTE	nw;
	ulong	dest_ip;
	BYTE	rSub;

	rSub = B_shm_ptr->IM_Buf.RSub;
	if (rSub != B_shm_ptr->IM_Buf.WSub)
	{
		GetBicc = &B_shm_ptr->IM_Buf.msgNum[rSub];
		sio = GetBicc->sio;
		dpc = GetBicc->dpc;
		sls = GetBicc->cic[0] & 0x0f;
		nw = (sio >> 6) & 3;
		pclen = pc_length(nw);
		len = GetBicc->len;

		dest_ip = GetBicc->dest_ip;
		if (dest_ip == 0xffffffff)
		{
			outlink = routingResult.biccMsgOutLink[rSub];
//			outlink = check_outbound_route(nw,dpc,sls);
			if ( outlink < 0 )
			{
				mtp3_debug(MTP3DB_ERROR,"receive message from UP,sio=%x,dpc=%lx",GetBicc->sio,GetBicc->dpc);
				mtp3_showbuf(MTP3DB_ERROR,GetBicc->msgList,GetBicc->len);
				mtp3_debug(MTP3DB_ERROR,"perform routing:Route Failure,Reason:program bug");
				B_shm_ptr->IM_Buf.RSub ++;
				mtp3.nw[nw].flow.MtoI_throwed[4]++;
				return 0;
			}
		}
		else
			outlink = GetBicc->link;
		msgptr = &mtp3_iprt.io_msg.msgContent[0];
		if (pclen == MTP3_24BIT_PC)
		{
			msgptr[1] = outlink>>8;
			msgptr[0] = outlink&0xff;
			msgptr[2] = (len + 12)/0xff;
			msgptr[3] = (len + 12)&0xff;
			msgptr[4] = sio;
			memcpy(&msgptr[5],&dpc,3);

			//memcpy(&msgptr[6],&mtp3_para->nw[nw].opc24,3);

			if (dest_ip == 0xffffffff)
			{
				if (GetBicc->opc == 0)
					memcpy(&msgptr[8],&mtp3_para->nw[nw].opc24,3);
				else
					memcpy(&msgptr[8],&GetBicc->opc,3);//keep the UP filled opc
			}
			else
				memcpy(&msgptr[8],&GetBicc->opc,3);//keep the UP filled opc

			msgptr[11] = GetBicc->cic[0] & 0x0f;
			memcpy(&msgptr[12],&GetBicc->cic[0],4);
			memcpy(&msgptr[16],&GetBicc->msgList,len);
		}
		else
		{
			//route_mark = (GetBicc->cic[0] << 28)+(mtp3_para->nw[nw].opc14 << 14)+dpc;

			if (dest_ip == 0xffffffff)
			{
				if (GetBicc->opc == 0)
					route_mark = (GetBicc->cic[0] << 28)+(mtp3_para->nw[nw].opc14 << 14)+dpc;
				else
					route_mark = (GetBicc->cic[0] << 28)+(GetBicc->opc << 14)+dpc;//keep the UP filled opc
			}
			else
				route_mark = (GetBicc->cic[0] << 28)+(GetBicc->opc << 14)+dpc;//keep the UP filled opc

			msgptr[1] = outlink>>8;
			msgptr[0] = outlink&0xff;
			msgptr[2] = (len + 9) / 0xff;
			msgptr[3] = (len+9) & 0xff;
			msgptr[4] = sio;
			memcpy(&msgptr[5],&route_mark,4);
			memcpy(&msgptr[9],&GetBicc->cic,4);
			memcpy(&msgptr[13],&GetBicc->msgList,len);
		}
		mtp3.nw[nw].flow.MtoI[4]++;
		if (dest_ip == 0xffffffff)
		{
			send_mtp_msg(outlink,msgptr);
		}
		else
		{
			mtp3_iprt.io_msg.msgLength = (msgptr[2]<<8) + msgptr[3]+3+1;
			if (iptrans_msg_flow(msgptr,pclen,MTP_MSG_OTHER_SERVER,dest_ip));
//			send_to_mtp2(dest_ip);
			send_to_mtp2_new_struct(dest_ip);
		}
		B_shm_ptr->IM_Buf.RSub ++;
	}
	return 1;
}

int	find_dst_place(long	dst,WORD lsno)
{
	BYTE	i;
	BYTE	nw;
	WORD	dpc_place;
	ls_info	*ls;

	if (lsno >= MAX_LS)
		return -1;

	ls = &mtp3.ls[lsno];
	nw = mtp3_para->ls_pro[lsno].nw_id;

	for ( i=0; i<(ls->influ_dstnum_asNLS % MAX_LS_DPC_ADD1); i++ )
	{
		dpc_place = ls->influ_dstplace_intable_asNLS[i];
		if ( mtp3_para->nw[nw].routing[dpc_place].dpc == dst )
			return dpc_place;
	}

	for ( i=0; i<(ls->influ_dstnum_asALS % MAX_LS_DPC_ADD1); i++ )
	{
		dpc_place = ls->influ_dstplace_intable_asALS[i];
		if ( mtp3_para->nw[nw].routing[dpc_place].dpc == dst )
			return dpc_place;
	}
	return -1;
}

int find_direct_ls_to_dst(long dst, BYTE nw, long opc)
{
	WORD	i, default_flag=0;

	if(pc_length(nw)==MTP3_14BIT_PC && opc == mtp3_para->nw[nw].opc14)
		default_flag = 1;
	else if(pc_length(nw)==MTP3_24BIT_PC && opc == mtp3_para->nw[nw].opc24)
		default_flag = 1;
		
	for (i=0; i<MAX_LS; i++)
	{
		if (mtp3_para->ls_pro[i].ls_op_pc == dst && ( (mtp3_para->ls_pro[i].nw_id) == nw))
		{
			if(mtp3_para->ls_pro[i].ls_opc == opc )
				return i;
			else if(mtp3_para->ls_pro[i].ls_opc == 0 && default_flag)
				return i;
		}
	}

	mtp3_debug(MTP3DB_EVENT,"dst %d opc %d Can't find direct linkset to destination",dst, opc);
	return MAX_LS;
}

int get_chl_via_slc(int linkset,BYTE slc,long msgopc, long msgdpc)
{
	ls_info *ls;
	int		lsx16;
	BYTE	nw;
	int		link;

	if (linkset >= MAX_LS)
		return -1;
	if (slc > 15)
		return -1;
	lsx16 = linkset << 4;
	ls = &mtp3.ls[linkset];
	if (mtp3_para->ls_pro[linkset].ls_op_pc == msgopc)
	{
		link = ls_slc[lsx16+slc];
		if 	( mtp3ObjState.lk_configured[link] == PARA_CONFIGURED )
			return ls_slc[lsx16+slc];
	}
	else
	{
		nw = mtp3_para->ls_pro[linkset].nw_id;
		linkset = find_direct_ls_to_dst(msgopc,nw, msgdpc);
		if ( linkset < MAX_LS )
		{
			lsx16 = linkset << 4;
			return ls_slc[lsx16+slc];
		}
	}
	mtp3_debug(MTP3DB_EVENT,"slc %d Can't Find This slc",slc);
	return -1;
}

void send_to_host_mtp3(BYTE *msgptr,ulong dst_ip)
{
   	mtp3_iprt.io_msg.msgSrcPort = SS7_PORT;
	mtp3_iprt.io_msg.msgDstPort = SS7_PORT;
	mtp3_iprt.io_msg.msgDstIP = dst_ip;
	mtp3_iprt.io_msg.msgLength = (msgptr[2]<<8) + msgptr[3]+3+1;
	memcpy(&mtp3_iprt.io_msg.msgContent, msgptr,mtp3_iprt.io_msg.msgLength);
//	mtp3_iprt.io_msg.msgContent[0] = msgptr[0];
//	iptrPutMessage(mtp3_iprt.io_msg);

	iptrDirectSendMsg(mtp3_iprt.io_msg);
}

void mtp3_multicast(BYTE *msgptr)
{
	int	i;
	ulong	dst_ip;

	for (i=0;i<MAX_MTP3_NUM;i++)
	{
		dst_ip = MTP3IPMng.mtp3_flag_ip[i];
		if ((MTP3IPMng.mtp3_flag_old[i] == 1) || (dst_ip==mtp3_localip))
		{
			send_to_host_mtp3(msgptr,dst_ip);
			mtp3_debug(MTP3DB_SNMMSG,"Multicast TFP/TFA to %lx",dst_ip);
		}

	}
}

void hmdt_SNM_message_for_distribution(BYTE	*msgptr,BYTE src_host)
{
	ls_info	*ls;
	int		link;
	int		chl;
	BYTE	msgtype_offset;/*message type offset */
	BYTE	msgtype;
	BYTE	h0;
	BYTE	h1;
	long	MsgOpc, MsgDpc;
	long	tfdst;
	BYTE	pc_len;
	int		sp_place;
	int		lsno;
	BYTE	nw;
	BYTE	slc;
	BYTE	remote_bsnt;
	int		i;

	link = msgptr[1]*256+msgptr[0];
	lsno = mtp3_para->lk[link].e1_to_linkset;
	if (lsno >= MAX_LS)
		return;
	ls = &mtp3.ls[lsno];

	nw = (msgptr[4] >> 6) & 3;
	pc_len = pc_length(nw);
	if (pc_len == MTP3_24BIT_PC)
	{
		msgtype_offset = 10+1+1;
		memcpy(&MsgOpc,&msgptr[8],3);
		memcpy(&MsgDpc, &msgptr[5],3);
		slc = msgptr[11] & 0x0f;
	}
	else
	{
		memcpy(&MsgOpc,&msgptr[5],4);
		slc = (MsgOpc >> 28) & 0x0f;
		MsgDpc = MsgOpc & 0x3fff;
		MsgOpc = (MsgOpc & 0x0fffffff) >> 14;
		msgtype_offset = 7+1+1;
	}

	msgtype = msgptr[msgtype_offset];
	h0 = msgtype & 0x0F;
	h1 = (msgtype >> 4) & 0x0f;
	switch (h0)
	{
		case 1:/* COO/COA/CBD/CBA */
			chl = get_chl_via_slc(lsno,slc,MsgOpc, MsgDpc);
			if (chl == -1)
				return;
			if ( (mtp3ObjState.lk_mtp3[chl] != mtp3_localip)	&&
				 (src_host == MSG_FROM_MTP2)				)
			{
				send_to_host_mtp3(msgptr, mtp3ObjState.lk_mtp3[chl]); //<< 16) | 0x010012ac);
				return;
			}
			switch (h1)
			{
			case 1:/* COO */
				remote_bsnt = msgptr[msgtype_offset+1];
				if (remote_bsnt < 128)
				{
					mtp3_debug(MTP3DB_EVENT,"link %d RVed COO",chl);
					mtp3ObjInput.tlac_input_from_hmdt[chl] = TLAC_HMDT_CHANGEOVER_ORDER;
					fsnc[chl] = msgptr[msgtype_offset+1];
				}
				else
				{
					mtp3_debug(MTP3DB_EVENT,"link %d RECEIVE COO WITH INVALID BSN",chl);
				}
				break;
			case 2:/* COA */
				remote_bsnt = msgptr[msgtype_offset+1];
				if (remote_bsnt < 128)
				{
					mtp3ObjInput.tcoc_input_from_hmdt[chl] = TCOC_HMDT_COA_COMMAND;
					mtp3_debug(MTP3DB_EVENT,"chl %d rv COA",chl);
//					printf("chl %d rv COA\n",chl);
					fsnc[chl] = msgptr[msgtype_offset+1];
				}
				else
				{
					mtp3_debug(MTP3DB_EVENT,"link %d RECEIVE COA WITH INVALID BSN",chl);
				}
				break;
			case 5:/* CBD */
				mtp3_debug(MTP3DB_EVENT,"chl %d rev cbd,tcbc state is %d",chl,mtp3ObjState.tcbc_state[chl]);
//				printf("chl %d rev cbd,tcbc state is %d\n",chl,mtp3ObjState.tcbc_state[chl]);
// tcbc_input can cause this var override in some case
//				tcbc_input[chl] = TCBC_HMDT_CBD_COMMAND;
				cbd_cbc_r[chl] = msgptr[msgtype_offset+1];
				hmrt_tcbc_changeback_ack(chl);
				break;
			case 6:/* CBA */
				mtp3_debug(MTP3DB_EVENT,"chl %d rev cba",chl);
//				printf("chl %d rev cba\n",chl);
//				tcbc_input[chl] = TCBC_HMDT_CBA_COMMAND;
				cba_cbc_r[chl] = msgptr[msgtype_offset+1];
				break;
			default:
				break;
			}
			break;
		case 2:/* ECO/ECA */
			chl = get_chl_via_slc(lsno,slc,MsgOpc, MsgDpc);
			if (chl == -1)
				return;
			switch (h1)
			{
			case 1:/* ECO */
				mtp3ObjInput.tlac_input_from_hmdt[chl] = TLAC_HMDT_ECHANGEOVER_ORDER;
				break;
			case 2:/* ECA */
				mtp3ObjInput.tcoc_input_from_hmdt[chl] = TCOC_HMDT_ECA_COMMAND;
				break;
			default:
				break;
			}
			break;
		case 4:/* TFP/TFA/ */
			switch (h1)
			{
				case 1:/* TFP */
					if (src_host == MSG_FROM_MTP2)
					{
						mtp3_multicast(msgptr);
						return;
					}
					if ( pc_len == MTP3_24BIT_PC )
					{
						memcpy(&tfdst,&msgptr[msgtype_offset+1],3);
					}
					else
					{
						memcpy(&tfdst,&msgptr[msgtype_offset+1],2);
						tfdst = tfdst & 0x3fff;
					}
					if (mtp3_para->ls_pro[lsno].ls_op_pc == tfdst)
						return;
					sp_place = find_dst_place(tfdst,lsno);
					if ( sp_place == -1 )
						return;
					TFPmsg_OPC = MsgOpc;
					TFPmsg_SrcLk = link;
					mtp3.nw[nw].rtpc_input[sp_place] = RTPC_TFP_MSG;
					rtpc_proc(nw,sp_place);
				break;

				case 5:/* TFA */
					if (src_host == MSG_FROM_MTP2)
					{
						mtp3_multicast(msgptr);
						return;
					}
					if ( pc_len == MTP3_24BIT_PC )
						memcpy(&tfdst,&msgptr[msgtype_offset+1],3);
					else
					{
						memcpy(&tfdst,&msgptr[msgtype_offset+1],2);
						tfdst = tfdst & 0x3fff;
					}
					if (mtp3_para->ls_pro[lsno].ls_op_pc == tfdst)
						return;
					sp_place = find_dst_place(tfdst,lsno);
					if ( sp_place == -1 )
						return;
					TFAmsg_OPC = MsgOpc;
					TFAmsg_SrcLk = link;
					mtp3.nw[nw].rtac_input[sp_place] = RTAC_TFA_MSG;
					rtac_proc(nw,sp_place);
				break;

				default:
				break;
			}
			break;
		case 5:/* RST */
			if ( pc_len == MTP3_24BIT_PC )
				memcpy(&tfdst,&msgptr[msgtype_offset+1],3);
			else
			{
				memcpy(&tfdst,&msgptr[msgtype_offset+1],2);
				tfdst = tfdst & 0x3fff;
			}
			sp_place = find_dst_place(tfdst,lsno);
			if (sp_place == -1)
				return;
			if ( ((mtp3.nw[nw].routine[sp_place] >> 4) & 3) != 1 )/* inaccessable */
			{
				mtp3.nw[nw].rtpc_input[sp_place] = RTPC_RSRT_SEND_TFP_MSG;
				sdTFP_Ls = lsno;/* send TFP to this linkset's remote sp */
				rtpc_proc(nw,sp_place);
			}
			else
			{
				mtp3.nw[nw].rtac_input[sp_place] = RTAC_SEND_TFA_MSG;
				sdTFA_Ls = lsno;
				rtac_proc(nw,sp_place);
			}
			break;
		case 6:/* inhibit message */
			chl = get_chl_via_slc(lsno,slc,MsgOpc, MsgDpc);
			if (chl == -1)
				return;
			if ( (mtp3ObjState.lk_mtp3[chl] != mtp3_localip)	&&
				 (src_host == MSG_FROM_MTP2)				)
			{
				send_to_host_mtp3(msgptr, mtp3ObjState.lk_mtp3[chl]);// << 16) | 0x010012ac);
				return;
			}

			switch (h1)
			{
				case 1:/* LIN */
					chl = get_chl_via_slc(lsno,slc,MsgOpc, MsgDpc);
					mtp3ObjInput.tlac_input_from_hmdt[chl] = TLAC_HMDT_INHIBIT_SIGLINK;
					break;
				case 2:/* LUN */
					chl = get_chl_via_slc(lsno,slc,MsgOpc, MsgDpc);
					mtp3ObjInput.tlac_input_from_hmdt[chl] = TLAC_HMDT_UINHIBIT_SIGLINK;
					break;
				case 3:/* LIA */
					chl = get_chl_via_slc(lsno,slc,MsgOpc, MsgDpc);
					mtp3ObjInput.tlac_input_from_hmdt[chl] = TLAC_HMDT_INHIBIT_ACK;
					break;
				case 4:/* LUA */
					chl = get_chl_via_slc(lsno,slc,MsgOpc, MsgDpc);
					mtp3ObjInput.tlac_input_from_hmdt[chl] = TLAC_HMDT_UNINHIBIT_ACK;
					break;
				case 5:/* LID */
					chl = get_chl_via_slc(lsno,slc,MsgOpc, MsgDpc);
					mtp3ObjInput.tlac_input_from_hmdt[chl] = TLAC_HMDT_INHIBIT_DENIED;
					break;
				case 6:/* LFU */
					chl = get_chl_via_slc(lsno,slc,MsgOpc, MsgDpc);
					mtp3ObjInput.tlac_input_from_hmdt[chl] = TLAC_HMDT_FORCE_UNINHIBIT_SIGLINK;
					break;
				case 7:/* LLT */
					chl = get_chl_via_slc(lsno,slc,MsgOpc, MsgDpc);
					mtp3ObjInput.tlac_input_from_hmdt[chl] = TLAC_HMDT_LOCAL_INHIBIT_TEST;
					break;
				case 8:/* LRT */
					chl = get_chl_via_slc(lsno,slc,MsgOpc, MsgDpc);
					mtp3ObjInput.tlac_input_from_hmdt[chl] = TLAC_HMDT_REMOTE_INHIBIT_TEST;
					break;
				default:
					break;
			}
			break;
		case 7:/* TRA */
			if (own_sp_restarting)/* sp restarting */
			{
				rv_TRA_num++;
			}
			else
			{
				lsno=find_direct_ls_to_dst(MsgOpc,nw, MsgDpc);
				if ( (lsno != -1)								&&
					 (mtp3.ls[lsno].adjacentsp_restarting==1)	)
				{/* from an restarting adjacent sp? */
					if (sending_phase_finished[lsno] == TRUE)
					{
						sending_phase_finished[lsno] = FALSE;
						stop_mtp3T21(lsno);
						tsrc_fun5(lsno);
					}
					else
					{
					}
				}
				else
				{
					for (i=0; i<MAX_ROUTE; i++)
					{
						if ( (mtp3.nw[nw].routine[i] & 0x30) == 0 )/* dst inaccessible */
						{
							if ( (mtp3_para->nw[nw].routing[i].normal_ls < MAX_LS)		||
								 (mtp3_para->nw[nw].routing[i].alternative_ls < MAX_LS))
							{
								mtp3.nw[nw].rtpc_input[i] = RTPC_TSRC_SEND_TFP_MSG;
								sdTFP_Ls = lsno;/* send TFP to this linkset's remote sp */
								tprc_proc(nw,i);
							}
						}
					}
				}
			}
			break;
		default:
			break;
	}
}

void hmdt_test_msg(BYTE *msgptr)
{
	int		i;
    WORD	chl;
	WORD	linkset;
    WORD	sp_place;
	ls_info	*ls=NULL;
	BYTE	nw;
	long	route_mark;
	BYTE	msg_LI;
	BYTE	len;
	BYTE	*sd_tmp_buf;
	ulong opc,dpc;
	BYTE	slc=0;

	chl = msgptr[1]*256+msgptr[0];
	linkset = mtp3_para->lk[chl].e1_to_linkset;
	nw = mtp3_para->ls_pro[linkset].nw_id;
	ls = &mtp3.ls[linkset];
	sp_place = ls->adjacent_sp_place;
	if (sp_place >= MAX_ROUTE)
		return;

    if( msgptr[12] == 0x11 && !(mtp3_para->lk[chl].admin_state & 0x01 ))
    {
    	mtp3_debug(MTP3DB_ERROR,"mtp3 link have been locked , discard sltm msg\r\n");
        return;
    }

	sd_tmp_buf = &mtp3_iprt.io_msg.msgContent[0];
	if (pc_length(nw) == MTP3_24BIT_PC)
    {/* For 24 Bit */
		if (msgptr[12] == 0x11  )
		{
			if (mtp3ObjState.lk_SpecANSI_flag[chl] == 1)
				slc = msgptr[13] & 0x0f;
			else
				slc = msgptr[11] & 0x0f;
			if (slc != mtp3_para->lk[chl].e1_to_slc)//slc incorrect
			{
				mtp3_debug(MTP3DB_ERROR,"MTP3<==MTP2,24BIT,link=%d,slc=%d incorrect,should be %d",chl,slc,mtp3_para->lk[chl].e1_to_slc);
				return;
			}
				memcpy(&dpc,&msgptr[5],3);
				memcpy(&opc,&msgptr[8],3);
				msg_LI = (msgptr[13] >> 4);
			sd_tmp_buf[0] = msgptr[0];
			sd_tmp_buf[1] = msgptr[1];
            sd_tmp_buf[2] = msgptr[2];
            sd_tmp_buf[3] = msgptr[3];
			if (mtp3ObjState.lk_SpecANSI_flag[chl] == 1)
				sd_tmp_buf[4] = (nw << 6)+2;
			else
				sd_tmp_buf[4] = (nw << 6)+1;
            memcpy(&sd_tmp_buf[5],&mtp3_para->ls_pro[linkset].ls_op_pc,3);
			//memcpy(&sd_tmp_buf[7],&mtp3_para->nw[nw].opc24,3);//??
			memcpy(&sd_tmp_buf[8],&dpc,3);
            sd_tmp_buf[11] = msgptr[11];
            sd_tmp_buf[12]= SIGNAL_SLTA;
            sd_tmp_buf[13] = msgptr[13];
            for (i=1; i<=msg_LI; i++)
            {
				len = i + 11+1;
				sd_tmp_buf[len+1] = msgptr[len+1];
	    }
			send_mtp_msg(chl,sd_tmp_buf);
	}
	else
	{
			if (msgptr[14] == (chl&0xFF))//???
			{

				mtp3ObjInput.sltc_input[chl] = SLTA_MSG;
				if (mtp3ObjState.sltc_state[chl] != 3)
            		sltc_proc(chl);
        	       }
        }
	}

	else/* 14 bit */
	{
		if (msgptr[9] == 0x11  )
		{
			if (mtp3ObjState.lk_SpecANSI_flag[chl] == 1)
				slc = msgptr[10] & 0x0f;
			else
				slc = (msgptr[8] >> 4) & 0x0f;
			if (slc != mtp3_para->lk[chl].e1_to_slc)//slc incorrect
			{
				mtp3_debug(MTP3DB_ERROR,"MTP3<==MTP2,14BIT,link=%d,slc=%d incorrect,should be %d",chl,slc,mtp3_para->lk[chl].e1_to_slc);
				return;
			}
				memcpy(&route_mark,&msgptr[5],4);
				dpc = route_mark & 0x3FFF;
				opc = (route_mark & 0x0FFFFFFF) >> 14;
			//route_mark = (mtp3_para->lk[chl].e1_to_slc << 28) + (mtp3_para->nw[nw].opc14 << 14) + (mtp3_para->ls_op_pc[linkset]);//??
			route_mark = (mtp3_para->lk[chl].e1_to_slc << 28) + (dpc<< 14) + (mtp3_para->ls_pro[linkset].ls_op_pc);
			msg_LI = (msgptr[10] >> 4);
			sd_tmp_buf[1] = chl>>8;
			sd_tmp_buf[0] = chl&0xff;
			sd_tmp_buf[2] = msgptr[2];
			sd_tmp_buf[3] = msgptr[3];
			if (mtp3ObjState.lk_SpecANSI_flag[chl] == 1)
				sd_tmp_buf[4] = (nw << 6) + 2;
			else
				sd_tmp_buf[4] = (nw << 6) + 1;
			memcpy(&sd_tmp_buf[5],&route_mark,4);
    	    sd_tmp_buf[9] = SIGNAL_SLTA;
        	for (i=0; i<=msg_LI; i++)
            {
				len = i+8+1;
                sd_tmp_buf[len+1] = msgptr[len+1];
			}
			send_mtp_msg(chl,sd_tmp_buf);
		}
        else
		{
			if (msgptr[11] == (chl&0xFF))//???
			{
           		mtp3ObjInput.sltc_input[chl] = SLTA_MSG;
           		if (mtp3ObjState.sltc_state[chl] != 3)
           			sltc_proc(chl);
			}
		}
	}
}

int mtp3_Trans_stpMsg(BYTE *msgptr,WORD outlink,BYTE pc_len)
{
	long	dest_ip = 0x00;
	BYTE	nw=0;
	BYTE	ssf=0;
	WORD len,link;
	
	link = msgptr[1]*256+msgptr[0];
	nw = (msgptr[4] >> 6) & 3;
	ssf = msgptr[4] & 7;
	len = (msgptr[2]<<8) + msgptr[3] + 3+1;

	if(len > MAX_SS7_MSG_LEN)
	{
		mtp3_debug(MTP3DB_ERROR,"mtp3_Trans_stpMsg, length longer than 300, len=%d!", len);
		msgptr[2] = 0;
		len = MAX_SS7_MSG_LEN;
	}
	if (ssf>1)
		ssf = ssf - 1;

    if (mtp3_para->lk[link].e1_to_linkset == mtp3_para->lk[outlink].e1_to_linkset)
    {//to avoid stp back to the incoming linkset
        mtp3.nw[nw].flow.stp_loop[ssf]++;
        return 0;
    }

//	current_measure->tf_measure1[3][wx5[nw]+ssf]+=len;/* octets */
	current_measure->tf_measure2[3][wx5[nw]+ssf]++;/* MSUs */
	mtp3.nw[nw].flow.stp[ssf]++;

	mtp3_iprt.io_msg.msgLength = len;
	mtp3_iprt.io_msg.msgContent[1] = outlink>>8;
	mtp3_iprt.io_msg.msgContent[0] = outlink&0xff;
	if (mtp3ObjState.lk_mtp3[outlink] != mtp3_localip)
	{
		dest_ip = mtp3ObjState.lk_mtp3[outlink];
		//dest_ip = (dest_ip << 16) | E1CARD_BASE_IP;
		if (iptrans_msg_flow(&mtp3_iprt.io_msg.msgContent[0],pc_len,MTP_MSG_STP,dest_ip));
//		send_to_mtp2(dest_ip);
		send_to_mtp2_new_struct(dest_ip);
	}
	else if (MTP3_LINK_TYPE(outlink) == LKTYPE_NONE_SIGTRAN)
	{
		dest_ip = LINK_TO_IP(outlink);
		if (iptrans_msg_flow(&mtp3_iprt.io_msg.msgContent[0],pc_len,MTP_MSG_STP,dest_ip));
		send_to_mtp2(dest_ip);
	}
	else
	{
#if _INCLUDE_M2UA
		if (MTP3_LINK_TYPE(outlink) == LKTYPE_MTP3_LITE)
		{
			if (iptrans_msg_flow(&mtp3_iprt.io_msg.msgContent[0],pc_len,MTP_MSG_STP,dest_ip));
			if ((msgptr[4] & 0x0f) == 3)//???
				put_mtp3lite_msg(msgptr);

		}
		else
		{
			if (iptrans_msg_flow(&mtp3_iprt.io_msg.msgContent[0],pc_len,MTP_MSG_STP,dest_ip));
			put_m2ua_msg((m2ua_up_msg_t *)msgptr);
			return 1;
		}
#endif
	}



	return 1;
}

void mtp3_print_routeFailure(BYTE sio,BYTE reason)
{
	BYTE	debug_type;

	switch(sio & 0x0f)
	{
		case 0x0:
			break;
		case 0x1:
			debug_type = MTP3DB_SNMMSG;
			break;
		case 0x3:
			debug_type = MTP3DB_SCCPMSG;
			break;
		case 0x4:
			debug_type = MTP3DB_TUPMSG;
			break;
		case 0x5:
			debug_type = MTP3DB_ISUPMSG;
			break;
		default:
			break;
	}

	switch (reason)
	{
		case 0:
			mtp3_debug(debug_type,"Perform routing:\33[31mRoute Failure,Reason:no route\33[0m");
			break;
		case 1:
			mtp3_debug(debug_type,"Perform routing:\33[31mRoute Failure,Reason:buf overflow\33[0m");
			break;
		case 2:
			mtp3_debug(debug_type,"Perform routing:\33[31mRoute Failure,Reason:network conflict\33[0m");
			break;
		default:
			break;
	}
}

int mtp3lite_updateStatus(WORD chl, BYTE new_l2_state,BYTE alarmCode)
{
	WORD	ls_t;

	if ((mtp3ObjState.lk_configured[chl] == PARA_NOT_CONFIGURED) ||
 		(mtp3_para->lk[chl].e1_to_mtp3 != mtp3_localip))
		return 0;

	ls_t = mtp3_para->lk[chl].e1_to_linkset;
	if(mtp3ObjState.link_l1_state[chl] == 0 && mtp3ObjState.link_l2_state[chl]!=0)
	{
		mtp3ObjState.link_l2_state[chl] = 0;//reset l2 state
	}	
	if (new_l2_state != mtp3ObjState.link_l2_state[chl])
	{
		if (new_l2_state == MTP2_STATE_WORKING)
		{
			current_measure->lk_measure1[chl][2]++;
			mtp3_debug(MTP3DB_EVENT,"mtp3-lite link %d L2 in service",chl);
			mtp3_send_mtp2_alarm(8+chl,0);
			//mtp3ObjInput.lsac_input_from_l2[chl] = LSAC_L2_IN_SERVICE;
    			mtp3ObjState.link_l1_state[chl] = 1;
    			mtp3ObjState.link_l2_state[chl] = MTP2_STATE_WORKING;
       		mtp3ObjState.lsac_state[chl] = LSAC_ACTIVE_STATE;
       		mtp3ObjState.sltc_state[chl] = SLTC_RUNNING_STATE;
       		mtp3ObjState.tlac_state[chl] = TLAC_AVAILABLE_STATE;
			if (mtp3.ls[ls_t].links_available == 0)
       			mtp3lite_upd_route_status(chl, 1);
			mtp3.ls[ls_t].links_available ++;
       		hmrt_tcbc_update_routing_tables(chl);
    			mtp3ObjState.link_l3_state[chl] = AVAILABLE;

       		mtp3ObjState.lk_mtp3[chl] = mtp3_localip;
		}
		else if (mtp3ObjState.link_l2_state[chl] == MTP2_STATE_WORKING)
		{
			local_change_over[chl]++;
			mtp3_debug(MTP3DB_EVENT,"mtp3-lite link %d L2 out of service",chl);
			mtp3_send_mtp2_alarm(8+chl,alarmCode);
			//mtp3ObjInput.lsac_input_from_l2[chl] = LSAC_L2_OUT_OF_SERVICE;
			//mtp3ObjInput.sltc_input[chl] = SLTC_STOP;
			//sltc_proc(chl);
			mtp3ObjState.link_l1_state[chl] = 0;
			mtp3ObjState.link_l2_state[chl] = 0;
   			mtp3ObjState.lsac_state[chl] = 0;
    			mtp3ObjState.sltc_state[chl] = 0;
    			mtp3ObjState.tlac_state[chl] = 0;
			if (mtp3.ls[ls_t].links_available > 0)
				mtp3.ls[ls_t].links_available --;
			if (mtp3.ls[ls_t].links_available == 0)
    			mtp3lite_upd_route_status(chl, 0);
    			hmrt_tcoc_update_routing_tables(chl);
			mtp3ObjState.link_l3_state[chl] = 0;
			
		}
	}

	return 1;
}

int	Link_Alternative_Mtp3_SubSystem_State(WORD Link, BYTE SubSystem)
{
	ulong	AlterMTP3=mtp3_para->lk[Link].e1_to_alterMTP3;
	int		Idx=-1;

	if ((Idx = MTP3_LinkIP_List(AlterMTP3,0)) >= 0)
	{
		if (SubSystem < 8)
		{
			return ((MTP3IPMng.LinkIPSubSta[Idx][0] >> SubSystem) & 1);
		}
		else
			return ((MTP3IPMng.LinkIPSubSta[Idx][1] >> (SubSystem & 7)) & 1);
	}

	return 0;
}

int check_stp_route(BYTE nw, long dpc, BYTE sls)
{
	long opc=0;
	int i=0, outlink=0;
	int max_opc=mtp3_opc.opc_num[nw];

	outlink = check_outbound_route(nw,dpc, sls, 0);
	if(outlink>=0)
		return outlink;
	for(i=0; i<max_opc; i++)
	{
		opc = mtp3_opc.opc[nw][i];
		outlink = check_outbound_route(nw,dpc, sls, opc);
		if(outlink>=0)
			return outlink;
	}
	return -1;
}

int	GetMtp2Msg(ulong ip_port)/* get ss7 message from iptrans via the 4950:ss7 port,4969:multicast port*/
{
	BYTE	module_id;
	BYTE	*msgptr=NULL;
	BYTE	sio;
	ls_info	*ls;
	long	route_mark;
	WORD	chl;
	BYTE routine;	
	BYTE	nw;
	BYTE	lsnw;
	BYTE	pc_len;
	int		outlink;
	BYTE	sls;
	WORD	lsno=0;
	ls_para *ls_pro=NULL;
	long	opc=0;
	long	msgdpc=0;
	long	msgopc=0;
	WORD len, tmp_len;
	BYTE	ssf;
	BYTE	printmsgsuccess;
	BYTE	src_host;
	BYTE	dpc_equal_to_opc;
	BYTE tmp_up_message[MAX_SS7_MSG_LEN+10];	

#if _INCLUDE_M2UA
	BYTE	new_l2_state;
	WORD	ls_t;
#endif

	printmsgsuccess = 0;
	outlink = MAX_LK_INDEX;
//	if (iptrGetMessage(&mtp3_iprt.io_msg,ip_port) > 0)
#if _INCLUDE_M2UA
	if (((ip_port == SS7_PORT) && (iptrDirectRecvMsg(&mtp3_iprt.io_msg,ip_port) > 0)) ||
		((ip_port == M2UA_PORT) && (!get_m2ua_msg(&mtp3_m2ua_msg))))
#else
	if (((ip_port == SS7_PORT) && (iptrDirectRecvMsg(&mtp3_iprt.io_msg,ip_port) > 0)))
#endif
	{
		if (ip_port == SS7_PORT)
		{
			msgSourceIP = mtp3_iprt.io_msg.msgSrcIP;
			module_id = (msgSourceIP >> 16) & 0xff;
	        	
					
			tmp_len = (mtp3_iprt.io_msg.msgContent[2]<<8 ) + mtp3_iprt.io_msg.msgContent[3];
			if ( ((msgSourceIP & E1CARD_BASE_IP) == E1CARD_BASE_IP) && (module_id < 32))//old structure: LINK,len,sio...
			{//insert one byte len in msgContent, change to new structure: LINK_high, Link_low , len_high,len_low,sio
				memcpy(tmp_up_message+3,  &mtp3_iprt.io_msg.msgContent[1], mtp3_iprt.io_msg.msgContent[1] + 1);
				tmp_up_message[1] = 0;
				tmp_up_message[0] = mtp3_iprt.io_msg.msgContent[0];//link
				tmp_up_message[2] = 0;
				memcpy(&mtp3_iprt.io_msg.msgContent[0], tmp_up_message, tmp_up_message[2]+4);
			}
			else if(tmp_len > MAX_SS7_MSG_LEN)//max len = 300
			{
				mtp3_debug(MTP3DB_ERROR,"Get message in SS7 port 4950, length longer than 300!");
				return 0;
			}
		}
#if _INCLUDE_M2UA
		if(ip_port == M2UA_PORT)
		{
			if(1)
			{//check len
				len = ntohs(mtp3_m2ua_msg->len)+3;
				if(len > MAX_SS7_MSG_LEN)
				{
					mtp3_debug(MTP3DB_ERROR,"Get message in m2ua, length longer than 300!");
					return 0;
				}
				len = 0;
			}
			if( mtp3_send_netcap && ( (mtp3_m2ua_msg->sio & 0xF0 ) != 0xF0 ) )
			    {
			        int pclen ;
			        sio = mtp3_m2ua_msg->sio;
			        nw = sio >> 6;
			    	pclen = pc_length(nw);

			    	if ( pclen == MTP3_24BIT_PC ) //ansi
			    	{
			    	    NcMtp3Send ( &mtp3_m2ua_msg->sio
			    	                 , ntohs(mtp3_m2ua_msg->len), 1 );
			    	}
			    	else if ( pclen == MTP3_14BIT_PC ) //ITU
			    	{
			    	    NcMtp3Send (  &mtp3_m2ua_msg->sio
			    	                 , ntohs(mtp3_m2ua_msg->len), 0 );
			    	}
			    }

		}
		else
#endif
		{
			if( mtp3_send_netcap && ( ( mtp3_iprt.io_msg.msgContent[4] & 0xF0 ) != 0xF0 ) )
			    {
			        int pclen ;
			        sio = mtp3_iprt.io_msg.msgContent[4];
			        nw = sio >> 6;
			    	pclen = pc_length(nw);

			    	if ( pclen == MTP3_24BIT_PC ) //ansi
			    	{
			    	    NcMtp3Send ( &mtp3_iprt.io_msg.msgContent[4]
			    	                 , (mtp3_iprt.io_msg.msgContent[2]<<8) + mtp3_iprt.io_msg.msgContent[3], 1 );
			    	}
			    	else if ( pclen == MTP3_14BIT_PC ) //ITU
			    	{
			    	    NcMtp3Send ( &mtp3_iprt.io_msg.msgContent[4]
			    	    	         , (mtp3_iprt.io_msg.msgContent[2]<<8) + mtp3_iprt.io_msg.msgContent[3], 0 );
			    	}
			    }
		}
		if (ip_port == SS7_PORT)
		{
			msgSourceIP = mtp3_iprt.io_msg.msgSrcIP;
			module_id = (msgSourceIP >> 16) & 0xff;
			msgptr = &mtp3_iprt.io_msg.msgContent[0];
	        	if ( ((msgSourceIP & E1CARD_BASE_IP) == E1CARD_BASE_IP) &&
	            	 (module_id < 32)                                   )
	          	{
	          		src_host = MSG_FROM_MTP2;
	          	}
	          	else
	          		src_host = MSG_FROM_MTP3;
		}
#ifdef _INCLUDE_M2UA
		else
		{
			src_host = MSG_FROM_MTP2;
			if (mtp3_m2ua_msg->sio == 0xEF)
			{
				mtp3_debug(MTP3DB_PRIMITIVE_MSG,"get M2UA heartbeat from %lx",msgSourceIP);
				mtp3_showbuf(MTP3DB_PRIMITIVE_MSG,(u8 *)&mtp3_m2ua_msg->link,ntohs(mtp3_m2ua_msg->len)+2);

				chl = mtp3_m2ua_msg->link;
				new_l2_state = mtp3_m2ua_msg->msg.lm.opercode;
				if(mtp3ObjState.link_l1_state[chl] == 0 && mtp3ObjState.link_l2_state[chl]!=0)
				{
					mtp3ObjState.link_l2_state[chl] = 0;//reset l2 state
				}
				if (new_l2_state == 0)
					mtp3ObjState.link_l1_state[chl] = 0;
				else
					mtp3ObjState.link_l1_state[chl] = 1;
				if ( (mtp3ObjState.lk_configured[chl] == PARA_NOT_CONFIGURED) ||
			 		(mtp3ObjState.lk_mtp3[chl] != mtp3_localip))
					return 0;

				if ( new_l2_state != mtp3ObjState.link_l2_state[chl] )
				{
					ls_t = mtp3_para->lk[chl].e1_to_linkset;
					if (new_l2_state == MTP2_STATE_WORKING)
					{
						current_measure->lk_measure1[chl][2]++;
						mtp3_debug(MTP3DB_EVENT,"link %d L2 in service",chl);
						mtp3ObjInput.lsac_input_from_l2[chl] = LSAC_L2_IN_SERVICE;
						mtp3_send_mtp2_alarm(8+mtp3_m2ua_msg->link,0);//clear alarm
					}
					else if (mtp3ObjState.link_l2_state[chl] == MTP2_STATE_WORKING)
					{
						local_change_over[chl]++;
						mtp3_debug(MTP3DB_EVENT,"link %d L2 out of service",chl);
						mtp3ObjInput.lsac_input_from_l2[chl] = LSAC_L2_OUT_OF_SERVICE;
						/*
						if ( mtp2->retrieved_bsnt[i] < 128 )
							local_bsnt_retrievable[chl] = TRUE;
						else
						{
							mtp3_debug(MTP3_DEBUG_LOG,"Link %d BSNT RETRIEVE FAILED",chl);
							local_bsnt_retrievable[chl] = FALSE;
						}
						*/
						mtp3ObjInput.sltc_input[chl] = SLTC_STOP;
						sltc_proc(chl);

						if (mtp3_m2ua_msg->msg.lm.alarmcode == 0)
							mtp3_send_mtp2_alarm(8+mtp3_m2ua_msg->link,M2UAALARM_Remote_MTP2_down);
						else
							mtp3_send_mtp2_alarm(8+mtp3_m2ua_msg->link,mtp3_m2ua_msg->msg.lm.alarmcode);
					}
				}
				mtp3ObjState.link_l2_state[chl] = new_l2_state;
				return 1;
			}
			else if (mtp3_m2ua_msg->sio == 0xEE)//sg
			{
				mtp3_send_alarm(MTP3_SG_COMPONENT+mtp3_m2ua_msg->link,mtp3_m2ua_msg->msg.lm.alarmcode);
			}
			else
			{
				msgptr 		= (BYTE *)mtp3_m2ua_msg;
				chl 		= msgptr[1]*256+msgptr[0];
				msgSourceIP = mtp3_para->sg[mtp3_para->lk[chl].e1_to_sg].ip;
/*				module_id 	= chl >> 3;
				msgSourceIP = module_id;
				msgSourceIP = (msgSourceIP << 16) | E1CARD_BASE_IP;*/
			}
		}
#endif

		chl = msgptr[1]*256+msgptr[0];
		len = (msgptr[2]<<8)+msgptr[3]+4;
		sio = msgptr[4];
		nw = sio >> 6;
		ssf = sio & 0x0f;
		if (ssf > 1)
			ssf--;
//		current_measure->tf_measure2[1][wx5[nw]+ssf]++;/* MSUs */
//		mtp3.nw[nw].flow.ItoM[ssf]++;

		pc_len = pc_length(nw);

		printmsgsuccess = iptrans_msg_flow(msgptr,pc_len,MTP_MSG_UP,msgSourceIP);
		if (src_host == MSG_FROM_MTP2)
		{

			current_measure->tf_measure2[1][wx5[nw]+ssf]++;/* MSUs */
			mtp3.nw[nw].flow.ItoM[ssf]++;
			src_host = MSG_FROM_MTP2;
			lsno = mtp3_para->lk[chl].e1_to_linkset;
			if (lsno >= MAX_LS)
			{
//				current_measure->tf_measure1[5][wx5[nw]+ssf]+=len;/* octets */
				current_measure->tf_measure2[5][wx5[nw]+ssf]++;/* MSUs */
				mtp3.nw[nw].flow.ItoM_throwed[ssf]++;
				return 0;
			}

			ls_pro = &mtp3_para->ls_pro[lsno];
			lsnw = ls_pro->nw_id;
			if (lsnw != nw)
			{
				if (printmsgsuccess == 1)
					mtp3_print_routeFailure(sio,2);
				else
				{
					mtp3_debug(MTP3DB_ERROR,"MTP3<==mtp2,%dBIT,SIO=%x,SPC(%lx->%lx),link=%d,linkset=%d",pc_len,sio,msgopc,msgdpc,chl,lsno);
					mtp3_showbuf(MTP3DB_ERROR,msgptr, (msgptr[2]<<8)+msgptr[3]+4);
					mtp3_debug(MTP3DB_ERROR,"Perform routing:linkset belong to net %d,but sio=%d",lsnw,sio);
				}
				mtp3.nw[nw].flow.ItoM_throwed[ssf]++;
				return 0;
			}

			if (lsno >=MAX_LS)
			{
//				current_measure->tf_measure1[5][wx5[nw]+ssf]+=len;/* octets */
				current_measure->tf_measure2[5][wx5[nw]+ssf]++;/* MSUs */
				mtp3.nw[nw].flow.ItoM_throwed[ssf]++;
				return 0;
			}
			ls = &mtp3.ls[lsno];

			if ( ls_pro->loopback_opt!= 0 )/* this linkset is loop back linkset */
			{
				nw = ls_pro->nw_id;
				if ( pc_length(nw) == MTP3_24BIT_PC )
				{
					opc = mtp3_para->ls_pro[lsno].ls_op_pc;
					memcpy( &msgptr[8],&opc,3);/* change msg's dpc to opc */
				}
				else
				{
					opc = mtp3_para->nw[nw].opc14;
					memcpy( (BYTE*)&route_mark,&msgptr[5],4);
					sls = (route_mark >> 28) & 0xf;
					route_mark = (sls << 28)+(mtp3_para->ls_pro[lsno].ls_op_pc << 14)+opc;
					memcpy(&msgptr[5],&route_mark,4);
				}
			}
			else if(0)// ( ls_pro & 0x10 )//??? change opc equal to our nw opc
			{
				if ( pc_length(nw) == MTP3_24BIT_PC )
				{
					memcpy( &msgptr[5], &mtp3_para->nw[nw].opc24, 3);/* change msg's dpc to opc */
				}
				else
				{
					memcpy( (BYTE*)&route_mark,&msgptr[5],4);
					route_mark = (route_mark & 0xFFFFC000) | (mtp3_para->nw[nw].opc14 & 0x3FFF);
					memcpy(&msgptr[5],&route_mark,4);
				}
			}

			if (pc_len == MTP3_24BIT_PC)
			{
				memcpy(&msgdpc,&msgptr[5],3);
				memcpy(&msgopc,&msgptr[8],3);
				dpc_equal_to_opc = mtp3_check_dpc_equal_to_opc(nw, msgdpc);

				//if (msgdpc != mtp3_para->nw[nw].opc24)/* STP */
				if (!dpc_equal_to_opc) //STP
				{
					sls = msgptr[11] & 0x0f;
					//outlink = check_outbound_route(nw,msgdpc,sls, 0);//??
					outlink = check_stp_route(nw,msgdpc,sls);						
					if (outlink >= 0)
					{
						if (ip_port == M2UA_PORT)
						{
							memcpy(mtp3_iprt.io_msg.msgContent, msgptr, len);
							msgptr = mtp3_iprt.io_msg.msgContent;
						}
						mtp3_Trans_stpMsg(msgptr,outlink,pc_len);
						return 1;
					}
				}
			}

			else/* 14 bit network */
			{
				memcpy(&route_mark,&msgptr[5],4);
				msgdpc = route_mark & 0x3FFF;
				msgopc = (route_mark & 0x0FFFFFFF) >> 14;
				dpc_equal_to_opc = mtp3_check_dpc_equal_to_opc(nw, msgdpc);

				//if (msgdpc != mtp3_para->nw[nw].opc14)/* STP !!! */
				if (!dpc_equal_to_opc)
				{
					sls = (route_mark >> 28) & 0x0f;
					//outlink = check_outbound_route(nw,msgdpc,sls, 0);//??
					outlink = check_stp_route(nw,msgdpc,sls);
					if (outlink >= 0)
					{
						if (ip_port == M2UA_PORT)
						{
							memcpy(mtp3_iprt.io_msg.msgContent, msgptr, len);
							msgptr = mtp3_iprt.io_msg.msgContent;
						}
						mtp3_Trans_stpMsg(msgptr,outlink,pc_len);
						return 1;
					}
				}
			}
		}
		else if (src_host == MSG_FROM_MTP3)
		{
#ifdef _M3UA_
			switch(sio)
			{
				case 0x1f://get route table from other plat					
					chl = msgptr[1]*256+msgptr[0];
					nw = msgptr[5];
					memcpy(&msgdpc, msgptr+6, 4);
					memcpy(&msgopc, msgptr+10, 4);
					routine = get_route_value(msgdpc, nw, msgopc);
					send_route_to_other_plat(msgdpc, nw, routine, mtp3_iprt.io_msg.msgSrcIP, chl, msgopc);
					return 1;
				case 0x2f:
					chl = msgptr[1]*256+msgptr[0];
					nw = msgptr[5];
					memcpy(&msgdpc, msgptr+6, 4);
					routine = msgptr[10];
					memcpy(&msgopc, msgptr+11, 4);
					update_route_by_other_plat(msgdpc,nw, routine, chl, msgopc);
					return 1;
				default:
					break;
			}

				
#endif
			if (pc_len == MTP3_24BIT_PC)
				memcpy(&msgdpc,&msgptr[5],3);
			else
			{
				memcpy(&route_mark,&msgptr[5],4);
				msgdpc = route_mark & 0x3FFF;
			}
			dpc_equal_to_opc = mtp3_check_dpc_equal_to_opc(nw, msgdpc);

			if (!dpc_equal_to_opc)
			{
				if (mtp3ObjState.lk_mtp3[chl] != mtp3_localip)
					return 0;

				if (MTP3_LINK_TYPE(chl) == LKTYPE_NONE_SIGTRAN)
					send_to_mtp2(LINK_TO_IP(chl));
#if _INCLUDE_M2UA
				else if (MTP3_LINK_TYPE(chl) == LKTYPE_SIGTRAN)
				{
					tmp_len = (mtp3_iprt.io_msg.msgContent[2]<<8) + mtp3_iprt.io_msg.msgContent[3];
					if(tmp_len > MAX_SS7_MSG_LEN)
					{
							mtp3_debug(MTP3DB_ERROR,"put_m2ua_msg, length longer than 300, len=%d!", tmp_len);
							mtp3_iprt.io_msg.msgContent[2] = 0;
							tmp_len= MAX_SS7_MSG_LEN;
					}
					put_m2ua_msg((m2ua_up_msg_t *) mtp3_iprt.io_msg.msgContent);
				}
				else if (MTP3_LINK_TYPE(chl) == LKTYPE_M3UA)
				{
					tmp_len = (mtp3_iprt.io_msg.msgContent[2]<<8) + mtp3_iprt.io_msg.msgContent[3];
					if(tmp_len > MAX_SS7_MSG_LEN)
					{
							mtp3_debug(MTP3DB_ERROR,"put_m3ua_msg, length longer than 300, len=%d!", tmp_len);
							mtp3_iprt.io_msg.msgContent[2] = 0;
							tmp_len= MAX_SS7_MSG_LEN;
					}
					send_mtp_msg(chl, mtp3_iprt.io_msg.msgContent);
				}
				else if (MTP3_LINK_TYPE(chl) == LKTYPE_MTP3_LITE)
				{
					mtp3_debug(MTP3DB_EVENT,"link %d get MTP3LITE msg from other plat and send it",chl);
					send_mtp_msg(chl, mtp3_iprt.io_msg.msgContent);
				}
#endif
				return 1;
			}
		}

		if (outlink < 0)
		{
			if (printmsgsuccess == 1)
				mtp3_print_routeFailure(sio,0);
			else
			{
				mtp3_debug(MTP3DB_ERROR,"MTP3<==MTP2,%dBIT,SIO=%x,SPC(%lx->%lx),link=%d",pc_len,sio,msgopc,msgdpc,chl);
//				mtp3_debug(msgptr,MTP3_ERROR_LOG,"\33[31m[STP]Route Failed!	SIO=%x,DPC=%lx\n\r\33[0m",sio,msgdpc);
				mtp3_showbuf(MTP3DB_ERROR,msgptr, (msgptr[2]<<8)+msgptr[3] + 4);
				mtp3_debug(MTP3DB_ERROR,"Perform routing:STP failed");
			}
			hmrt_srm_msg(lsno,SIGNAL_TFP,msgdpc);
//			current_measure->tf_measure1[5][wx5[nw]+ssf]+=len;/* octets */
			current_measure->tf_measure2[5][wx5[nw]+ssf]++;/* MSUs */
			mtp3.nw[nw].flow.stp_throwed[ssf]++;
			return 0;
		}

//		current_measure->tf_measure1[2][wx5[nw]+ssf]+=len;/* octets */
		current_measure->tf_measure2[2][wx5[nw]+ssf]++;/* MSUs */
		switch (sio & 0x0f)
		{
			case MTP3_SUB_SNM:
				mtp3.nw[nw].flow.MtoU[0]++;
				hmdt_SNM_message_for_distribution(msgptr,src_host);
				return 1;
			case MTP3_SUB_STM:
				mtp3.nw[nw].flow.MtoU[1]++;
				hmdt_test_msg(msgptr);
				return 1;
			case MTP3_SUB_STM2:
				mtp3ObjState.lk_SpecANSI_flag[chl] = 1;//mark special T+M
				mtp3.nw[nw].flow.MtoU[1]++;
				hmdt_test_msg(msgptr);
				return 1;
			case MTP3_SUB_SCCP:
				if ((mtp3_heartbeat.SubState[0] & 0x08) || (MSG_FROM_MTP3==src_host))
				{
					if ( (S_shm_ptr->MS_Buf.WSub+1) == S_shm_ptr->MS_Buf.RSub)// buffer overflow
					{
						mtp3.nw[nw].flow.MtoU_throwed[0]++;
						break;
					}
					send_to_sccp(msgptr);
					if (printmsgsuccess == 1)
						mtp3_debug(MTP3DB_SCCPMSG,"Perform routing:transfer to SCCP");
				}
				else if (Link_Alternative_Mtp3_SubSystem_State(chl,MTP3_SUB_SCCP))
				{
//					send_to_mtp2(mtp3_para->lk[chl].e1_to_alterMTP3);
					send_to_mtp2_new_struct(mtp3_para->lk[chl].e1_to_alterMTP3);
					if (printmsgsuccess == 1)
						mtp3_debug(MTP3DB_SCCPMSG,"Perform routing:SCCP UP is Locked,transfer to Alternative SCCP UP");
				}
				else
				{
					if (printmsgsuccess == 1)
						mtp3_debug(MTP3DB_ERROR,"Perform routing:No SCCP UP Available");
				}

				return 1;
			case MTP3_SUB_TUP:
				if ((mtp3_heartbeat.SubState[0] & 0x10) || (MSG_FROM_MTP3==src_host))
				{
					if ( (T_shm_ptr->MT_Buf.WSub+1) == T_shm_ptr->MT_Buf.RSub)// buffer overflow
					{
						mtp3.nw[nw].flow.MtoU_throwed[1]++;
						break;
					}
					send_to_tup(msgptr);
					if (printmsgsuccess == 1)
						mtp3_debug(MTP3DB_TUPMSG,"Perform routing:transfer to TUP");
				}
				else if (Link_Alternative_Mtp3_SubSystem_State(chl,MTP3_SUB_TUP))
				{
//					send_to_mtp2(mtp3_para->lk[chl].e1_to_alterMTP3);
					send_to_mtp2_new_struct(mtp3_para->lk[chl].e1_to_alterMTP3);
					if (printmsgsuccess == 1)
						mtp3_debug(MTP3DB_TUPMSG,"Perform routing:TUP UP is Locked,transfer to Alternative TUP UP");
				}
				else
				{
					if (printmsgsuccess == 1)
						mtp3_debug(MTP3DB_ERROR,"Perform routing:No TUP UP Available");
				}
				return 1;
			case MTP3_SUB_ISUP:
				if ((mtp3_heartbeat.SubState[0] & 0x20) || (MSG_FROM_MTP3==src_host))
				{
					if ( (I_shm_ptr->MI_Buf.WSub+1) == I_shm_ptr->MI_Buf.RSub)// buffer overflow
					{
						mtp3.nw[nw].flow.MtoU_throwed[2]++;
						break;
					}
					send_to_isup(msgptr);
					if (printmsgsuccess == 1)
						mtp3_debug(MTP3DB_ISUPMSG,"Perform routing:transfer to ISUP");
				}
				else if (Link_Alternative_Mtp3_SubSystem_State(chl,MTP3_SUB_ISUP))
				{
//					send_to_mtp2(mtp3_para->lk[chl].e1_to_alterMTP3);
					send_to_mtp2_new_struct(mtp3_para->lk[chl].e1_to_alterMTP3);
					if (printmsgsuccess == 1)
						mtp3_debug(MTP3DB_ISUPMSG,"Perform routing:ISUP UP is Locked,transfer to Alternative ISUP UP");
				}
				else
				{
					if (printmsgsuccess == 1)
						mtp3_debug(MTP3DB_ERROR,"Perform routing:No ISUP UP Available");
				}
				return 1;
			case MTP3_SUB_BICC:	// BICC
				if ((mtp3_heartbeat.SubState[1] & 0x40) || (MSG_FROM_MTP3==src_host))
				{
					if ( (B_shm_ptr->MI_Buf.WSub+1) == B_shm_ptr->MI_Buf.RSub)// buffer overflow
					{
						mtp3.nw[nw].flow.MtoU_throwed[2]++;
						break;
					}
					send_to_bicc(msgptr);
					if (printmsgsuccess == 1)
						mtp3_debug(MTP3DB_BICCMSG,"Perform routing:transfer to BICC");
				}
				else if (Link_Alternative_Mtp3_SubSystem_State(chl,MTP3_SUB_BICC))
				{
//					send_to_mtp2(mtp3_para->lk[chl].e1_to_alterMTP3);
					send_to_mtp2_new_struct(mtp3_para->lk[chl].e1_to_alterMTP3);
					if (printmsgsuccess == 1)
						mtp3_debug(MTP3DB_BICCMSG,"Perform routing:BICC UP is Locked,transfer to Alternative BICC UP");
				}
				else
				{
					if (printmsgsuccess == 1)
						mtp3_debug(MTP3DB_ERROR,"Perform routing:No BICC UP Available");
				}
				return 1;
			default:
				break;
		}
		if (printmsgsuccess == 1)
			mtp3_print_routeFailure(sio,1);
		else
		{
			mtp3_debug(MTP3DB_ERROR,"MTP3<==MTP2,%dBIT,SIO=%x,SPC(%lx->%lx),link=%d",pc_len,sio,msgopc,msgdpc,chl);
			mtp3_showbuf(MTP3DB_ERROR,msgptr, (msgptr[2]<<8)+msgptr[3]+4);
			mtp3_debug(MTP3DB_ERROR,"Perform routing:buffer fulled");
		}
		mtp3.nw[nw].flow.ItoM_throwed[ssf]++;
		return 0;
	}
	return 1;
}

#ifdef _M3UA_
int	m3ua_send_to_sccp(xua_m3ua_msg *msgptr)/* send sccp msg to tele user part */
{
	up_message *ToSccp;
	WORD		len;
	BYTE		nw;
	BYTE		link;

//	sio = msgptr[3];
   	ToSccp = &S_shm_ptr->MS_Buf.msgNum[S_shm_ptr->MS_Buf.WSub];
	nw = msgptr->ni;
   		ToSccp->sio = (nw <<6) | msgptr->si;
	  ToSccp->sio = ToSccp->sio & 0xEF;//init spare bit		
   		ToSccp->sio = ToSccp->sio | (mtp3_ansiFlag(nw) << 4);
//	sio = sio | (mtp3_ansiFlag(nw) << 4);
	link = msgptr->link;
	ToSccp->link = link;
	ToSccp->dest_ip = msgSourceIP;

//	pclen = pc_length(nw);
//	if (pclen == MTP3_24BIT_PC)/* for 24bit ss7 network */
//   	{
//   		if (msgptr[1] == 0 && msgptr[2] < 9)//len < 9
//   		{
//   			mtp3ObjState.MTP3WatchDog[3]++;
//   			mtp3.nw[nw].flow.MtoU_throwed[0]++;
//			mtp3_debug(MTP3DB_ERROR,"[SCCP]MTP3<==MTP2,LI over range and discarded! LI=%02d,Link=%d",msgptr[2],link);
//   			return 0;
//   		}

//		memcpy((BYTE *)&ToSccp->dpc,msgptr+4,3);/* message's dpc */
//		memcpy((BYTE *)&ToSccp->opc,&msgptr[7],3);/* message's opc */
			ToSccp->dpc = msgptr->dpc;
			ToSccp->opc = msgptr->opc;

   		ToSccp->cic[0] = msgptr->sls;
//   		len = (msgptr[1]<<8) + msgptr[2]-8;
			len = ntohs(msgptr->len);
   		ToSccp->len = len;
   		memcpy(&ToSccp->msgList,msgptr->content, len);
	S_shm_ptr->MS_Buf.WSub ++;
	mtp3.nw[nw].flow.MtoU[2]++;
	return 1;
}

int	m3ua_send_to_bicc(xua_m3ua_msg *msgptr)/* send isup msg to tele user part */
{
	WORD 			len;
	up_message_2 	*ToBicc;
	BYTE			nw;

	ToBicc = &B_shm_ptr->MI_Buf.msgNum[B_shm_ptr->MI_Buf.WSub];
	nw = msgptr->ni;
	  ToBicc->sio = (nw<<6) | msgptr->si;
	  ToBicc->sio = ToBicc->sio & 0xEF;//init spare bit
	  ToBicc->sio = ToBicc->sio | (mtp3_ansiFlag(nw) << 4);
	ToBicc->link = msgptr->link;
	ToBicc->dest_ip = msgSourceIP;
	ToBicc->dpc = msgptr->dpc;
	ToBicc->opc = msgptr->opc;
	ToBicc->cic[0] = msgptr->content[0];
	ToBicc->cic[1] = msgptr->content[1];
	ToBicc->cic[2] = msgptr->content[2];
	ToBicc->cic[3] = msgptr->content[3];
	len = ntohs(msgptr->len);
	ToBicc->len = len-4;
	memcpy(&ToBicc->msgList,&msgptr->content[4],len);
	B_shm_ptr->MI_Buf.WSub ++;
	mtp3.nw[nw].flow.MtoU[4]++;
	return 1;
}

int	m3ua_send_to_isup(xua_m3ua_msg *msgptr)/* send isup msg to tele user part */
{
	WORD 		len;
	up_message *ToIsup;
	BYTE		nw;

	ToIsup = &I_shm_ptr->MI_Buf.msgNum[I_shm_ptr->MI_Buf.WSub];
	nw = msgptr->ni;
	ToIsup->sio = (nw<<6) | msgptr->si;
	ToIsup->sio = ToIsup->sio & 0xEF;//init spare bit	
	ToIsup->sio = ToIsup->sio | (mtp3_ansiFlag(nw) << 4);
	ToIsup->link = msgptr->link;//???
	ToIsup->dest_ip = msgSourceIP;
   		if (msgptr->len <= 0)
   		{
   			mtp3ObjState.MTP3WatchDog[7]++;
   			mtp3.nw[nw].flow.MtoU_throwed[2]++;
			mtp3_debug(MTP3DB_ERROR,"[ISUP]MTP3<==MTP2,LI over range and discarded! LI=%02d,Link=%d",msgptr->len, msgptr->link);
   			return 0;
   		}
	ToIsup->dpc = msgptr->dpc;
	ToIsup->opc = msgptr->opc;
	ToIsup->cic[0] = msgptr->content[0];
	ToIsup->cic[1] = msgptr->content[1];
	len = ntohs(msgptr->len) -2;
	ToIsup->len = len;
	memcpy(&ToIsup->msgList,&msgptr->content[2],len);
	MTP3_recv_isup_count(nw,msgptr->content[2]);
	I_shm_ptr->MI_Buf.WSub ++;
	mtp3.nw[nw].flow.MtoU[4]++;
	return 1;
}

int	m3ua_send_to_tup(xua_m3ua_msg *msgptr)/* send tup msg to tele user part */
{
	WORD		len;
	up_message	*ToTup;
	BYTE		nw;

	ToTup = &T_shm_ptr->MT_Buf.msgNum[T_shm_ptr->MT_Buf.WSub];
	nw = msgptr->ni;
	ToTup->sio = (nw<<6) | msgptr->si;
	ToTup->sio = ToTup->sio & 0xEF;//init spare bit		
	ToTup->sio = ToTup->sio | (mtp3_ansiFlag(nw) << 4);
	ToTup->link = msgptr->link;
	ToTup->dest_ip = msgSourceIP;
   		if (msgptr->len <= 0)
   		{
   			mtp3ObjState.MTP3WatchDog[5]++;
   			mtp3.nw[nw].flow.MtoU_throwed[1]++;
			mtp3_debug(MTP3DB_ERROR,"[TUP]MTP3<==MTP2,LI over range and discarded! LI=%02d,Link=%d",msgptr->len,msgptr->link);
   			return 0;
   		}
	ToTup->dpc = msgptr->dpc;/* message's dpc */
	ToTup->opc = msgptr->opc;/* message's opc */
	ToTup->cic[0] = msgptr->content[0];
	ToTup->cic[1] = msgptr->content[1];
	len = ntohs(msgptr->len) - 2;
	ToTup->len = len;
	memcpy(&ToTup->msgList,&msgptr->content[2],len);
	T_shm_ptr->MT_Buf.WSub ++;
	mtp3.nw[nw].flow.MtoU[3]++;
	return 1;
}

int check_m3ua_rc_verify(DWORD rc, WORD link)
{
	int dpc_index;
	WORD ls_t;

	ls_t = mtp3_para->lk[link].e1_to_linkset;	
	dpc_index = find_rc_dst_place(rc, ls_t);

	if(dpc_index >=0 && dpc_index < 256)
		return 1;
	else 
		return -1;
}

int get_m3ua_rc_by_dpc(BYTE nw, long dpc, long opc)//??-
{
	network	*sp;
	WORD	i;
	mtp3DPCIndex	*sort_rec = &mtp3SortRoutine.nw[nw];
	int		index;
	ull opc_dpc=0;

	if (dpc==0)
		return -3;

	sp = &mtp3.nw[nw];
	if(opc == mtp3_para->nw[nw].opc14 && (pc_length(nw)==MTP3_14BIT_PC))
		opc = 0;
	else if(opc == mtp3_para->nw[nw].opc24 && (pc_length(nw)==MTP3_24BIT_PC))
		opc = 0;
	opc_dpc = opc;
	opc_dpc = (opc_dpc <<32)|dpc;
	index = Mtp3BinSearchValue(0,sort_rec->sortedNum-1,nw,opc_dpc);//??-
	if ((index >= 0) && (index < MAX_ROUTE))
		i = sort_rec->index[index];
	else
		return -3;
	return mtp3_para->nw[nw].routing[i].rc;
}

int find_rc_dst_place(DWORD rc, WORD lsno)
{
	BYTE	i;
	BYTE	nw;
	BYTE	dpc_place;
	ls_info	*ls;

	if (lsno >= MAX_LS)
		return -1;

	ls = &mtp3.ls[lsno];
	nw = mtp3_para->ls_pro[lsno].nw_id;

		for ( i=0; i<(ls->influ_dstnum_asNLS % MAX_LS_DPC_ADD1); i++ )
		{
			dpc_place = ls->influ_dstplace_intable_asNLS[i];
			if ( mtp3_para->nw[nw].routing[dpc_place].rc == rc )
			{
				return dpc_place;
			}
		}
		for ( i=0; i<(ls->influ_dstnum_asALS % MAX_LS_DPC_ADD1); i++ )
		{
			dpc_place = ls->influ_dstplace_intable_asALS[i];
			if ( mtp3_para->nw[nw].routing[dpc_place].rc == rc )
			{
				return dpc_place;
			}	
		}

	return -1;
}

void m3ua_upd_route_status(WORD chl, DWORD rc, BYTE rc_status, BYTE ls_disable)
{
	ls_info	*ls;
	int		i,j;
	WORD lsno,spplace;//, als_spplace;
	int	dpc_index;
	WORD	lsx16;
	ulong dpc,opc;
	BYTE	*routine, nw;
	network	*sp;	
	lsno = mtp3_para->lk[chl].e1_to_linkset;

	
	if (lsno >= MAX_LS)
		return;

	ls = &mtp3.ls[lsno];
	nw = mtp3_para->ls_pro[lsno].nw_id;
	lsx16 = lsno << 4;
	sp = &mtp3.nw[nw];

	if(!ls_disable)
	{
		dpc_index = find_rc_dst_place(rc, lsno);
		if(dpc_index == -1 || dpc_index > MAX_ROUTE)
				return;
		if(rc==0)
		{
			dpc = mtp3_para->ls_pro[lsno].ls_op_pc;
			
		}
		else 
		{
			dpc = mtp3_para->nw[nw].routing[dpc_index].dpc;
			opc = mtp3_para->nw[nw].routing[dpc_index].opc;

		}
	}

	if (rc_status!=5)
	{//			mark_normal_linkset_unavailable(&mtp3.nw[nw].routine[dpc_index]);
		for ( i=0; i<(ls->influ_dstnum_asNLS % MAX_LS_DPC_ADD1); i++ )
		{
			spplace = ls->influ_dstplace_intable_asNLS[i];

		//	if(mtp3_para->nw[nw].routing[spplace].rc != rc && ls_disable==0)
		//		continue;
			if( ls_disable == 0)
				continue;
			
//			sp->m3ua_rc_status[spplace] = rc_status;
			if(detail_debug_flag)
			mtp3_debug(MTP3DB_EVENT," <%s.%d> M3UA update route info, link=%d, sppace=%d, sp->routine=%d", 
				__FUNCTION__,
				__LINE__,
				chl,
				spplace, sp->routine[spplace]);

			mark_normal_linkset_unavailable(&sp->routine[spplace]);

			if ( ((sp->routine[spplace] >> 2) & 3) == 0 )/*alternative route available */
				sp->routine[spplace] = (sp->routine[spplace] & 0x3f) + 0x40;/* current route change from normal linkset to alternative linkset */
			else/* sp not accessible */
			{
				sp_unaccessable((BYTE *)&sp->routine[spplace]);
				primitive_to_userpart(nw,mtp3_para->nw[nw].routing[spplace].dpc,UNAVAILABLE);
				sp->m3ua_rc_status[spplace] = rc_status;			
			}
			if(mtp3ObjState.lk_mtp3[chl] == mtp3_localip)
			{
				if(1)
				if(mtp_peer_ip != 0)
				{
					send_route_to_other_plat(mtp3_para->nw[nw].routing[spplace].dpc, 
						nw, 
						sp->routine[spplace], 
						mtp_peer_ip, 
						chl, 
						mtp3_para->nw[nw].routing[spplace].opc);
				}
				
				if( mtp3_para->lk[chl].e1_to_alterMTP3 !=0)
					send_route_to_other_plat(mtp3_para->nw[nw].routing[spplace].dpc, nw, sp->routine[spplace], mtp3_para->lk[chl].e1_to_alterMTP3, chl, mtp3_para->nw[nw].routing[spplace].opc);
				else if(mtp3_alterip!=0)
					send_route_to_other_plat(mtp3_para->nw[nw].routing[spplace].dpc, nw, sp->routine[spplace], mtp3_alterip, chl, mtp3_para->nw[nw].routing[spplace].opc);
			}
			if(detail_debug_flag)			
			mtp3_debug(MTP3DB_EVENT," <%s.%d> M3UA update route info, link=%d, sppace=%d, sp->routine=%d", 
				__FUNCTION__,
				__LINE__,
				chl,
				spplace, sp->routine[spplace]);
			
		}

		for ( i=0; i<(ls->influ_dstnum_asALS % MAX_LS_DPC_ADD1); i++ )
		{
			spplace = ls->influ_dstplace_intable_asALS[i];
			//if(mtp3_para->nw[nw].routing[spplace].rc != rc && ls_disable==0)
			//	continue;
			if(ls_disable == 0)
				continue;


			//sp->m3ua_rc_status[spplace] = rc_status;
			if(detail_debug_flag)
			mtp3_debug(MTP3DB_EVENT," <%s.%d> M3UA ALS update route info, link=%d, sppace=%d, sp->routine=%d, rc_status=%d", 
				__FUNCTION__,
				__LINE__,
				chl,
				spplace, sp->routine[spplace],
				sp->m3ua_rc_status[spplace]);
			
			mark_alternative_linkset_unavailable(&sp->routine[spplace]);
			
			if ( (sp->routine[spplace] & 3) != 0 )/* normal route unavailable  */
			{
				sp_unaccessable((BYTE *)&sp->routine[spplace]);
				primitive_to_userpart(nw,mtp3_para->nw[nw].routing[spplace].dpc,UNAVAILABLE);
				sp->m3ua_rc_status[spplace] = rc_status;
				
			}
			if(mtp3ObjState.lk_mtp3[chl] == mtp3_localip)
			{
				if(1)
				if(mtp_peer_ip != 0)
				{
					send_route_to_other_plat(mtp3_para->nw[nw].routing[spplace].dpc, 
						nw, 
						sp->routine[spplace], 
						mtp_peer_ip, 
						chl, 
						mtp3_para->nw[nw].routing[spplace].opc);
				}
				
				if(mtp3_para->lk[chl].e1_to_alterMTP3 !=0)
					send_route_to_other_plat(mtp3_para->nw[nw].routing[spplace].dpc, nw, sp->routine[spplace], mtp3_para->lk[chl].e1_to_alterMTP3, chl, mtp3_para->nw[nw].routing[spplace].opc);
				else if(mtp3_alterip!=0)
					send_route_to_other_plat(mtp3_para->nw[nw].routing[spplace].dpc, nw, sp->routine[spplace], mtp3_alterip, chl, mtp3_para->nw[nw].routing[spplace].opc);
			}
			if(detail_debug_flag)			
			mtp3_debug(MTP3DB_EVENT," <%s.%d> M3UA ALS update route info, link=%d, sppace=%d, sp->routine=%d", 
				__FUNCTION__,
				__LINE__,
				chl,
				spplace, sp->routine[spplace]);
			
		}
		if(ls_disable)
		{
			//memset(&ls_sls[lsx16],MAX_LK-1,16);
			for(i=0; i<16; i++)
			{
				//if(sls_to_link[lsx16+i] == chl)
					ls_sls[lsx16+i] = MAX_LK_INDEX;
			}
			set_heartbeat(ALARM_LS_UNAVAILABLE,lsno);
			mtp3_para->ls_pro[lsno].ls_state = 0;//ALARM_LS_UNAVAILABLE;
		}


	}
	else
	{
		for ( i=0; i<(ls->influ_dstnum_asNLS % MAX_LS_DPC_ADD1); i++ )
		{
			spplace = ls->influ_dstplace_intable_asNLS[i];
			//if(mtp3_para->nw[nw].routing[spplace].rc != rc && ls_disable==0)
			//	continue;

			routine = (BYTE *)&mtp3.nw[nw].routine[spplace];

			/*
			if(m2ua_get_traffic_mode_type()==0)
			{
				if(*routine  != 24 )
				{
					ls->send_asp_ac_link_id = chl;

					send_command_to_m3ua(chl, 1,M3UA_RC_CMD , rc, 0);

					mtp3_debug(MTP3DB_EVENT,"<%s:%d> M3UA send RC_CMD, link=%d, sppace=%d, sp->routine=%d", 
									__FUNCTION, __LINE__,
									chl, spplace, sp->routine[spplace]);			
				}
			}
			*/
			
			sp->m3ua_rc_status[spplace] = rc_status;
			set_heartbeat(ALARM_LS_AVAILABLE,lsno);
			mtp3_para->ls_pro[lsno].ls_state = 1;//ALARM_LS_AVAILABLE;
			//memset(&ls_sls[lsx16],chl,16);
			for(j=0; j<16; j++)
			{
				if(sls_to_link[lsx16+j] == chl)
					ls_sls[lsx16+j] = chl;
			}
			
			mark_normal_linkset_available(&mtp3.nw[nw].routine[spplace]);
			routine = (BYTE *)&mtp3.nw[nw].routine[spplace];
			if(detail_debug_flag)			
			mtp3_debug(MTP3DB_EVENT," <%s.%d> S5,M3UA update route info, link=%d, sppace=%d, sp->routine=%d", 
				__FUNCTION__,
				__LINE__,
				chl,
				spplace, sp->routine[spplace]);
			
			if (Nlinkset_status(*routine) == LS_AVAILABLE)
				*routine = ((*routine) & 0x3f);// current route is normal linkset 
			else if (Alinkset_status(*routine) == LS_AVAILABLE)
				(*routine) = ((*routine) & 0x3f) + 0x40;
			else
			{
				(*routine) = ((*routine) & 0x3f) + 0x80;
				primitive_to_userpart(nw,mtp3_para->nw[nw].routing[spplace].dpc,AVAILABLE);
			}

			if(1)
			if(mtp3ObjState.lk_mtp3[chl] == mtp3_localip && mtp_peer_ip != 0)
			{
				send_route_to_other_plat(dpc, 
					nw, 
					sp->routine[spplace], 
					mtp_peer_ip, 
					chl, 
					opc);				
			}
			
			if(mtp3ObjState.lk_mtp3[chl] == mtp3_localip && mtp3_para->lk[chl].e1_to_alterMTP3 !=0)
				send_route_to_other_plat(dpc, nw, sp->routine[spplace], mtp3_para->lk[chl].e1_to_alterMTP3, chl, opc);				

			if(detail_debug_flag)			
			mtp3_debug(MTP3DB_EVENT," <%s.%d> S5,M3UA update route info, link=%d, sppace=%d, sp->routine=%d", 
				__FUNCTION__,
				__LINE__,
				chl,
				spplace, sp->routine[spplace]);

			rc_timer = 100; //make sure 1 second later to send ASP_AC
			
		}
		sp = &mtp3.nw[nw];
		for ( i=0; i<(ls->influ_dstnum_asALS % MAX_LS_DPC_ADD1); i++ )
		{
			spplace = ls->influ_dstplace_intable_asALS[i];
			//if(mtp3_para->nw[nw].routing[spplace].rc != rc)
			//	continue;
			sp->m3ua_rc_status[spplace] = rc_status;
			routine = (BYTE*)&sp->routine[spplace];
			
			if(detail_debug_flag)			
			mtp3_debug(MTP3DB_EVENT," <%s:%d> S5 ALS,M3UA update route info, link=%d, sppace=%d, sp->routine=%d", 
				__FUNCTION__, __LINE__,
				chl,
				spplace, *routine);

			mark_alternative_linkset_available(&mtp3.nw[nw].routine[spplace]); //17-11-07
			routine = (BYTE *)&mtp3.nw[nw].routine[spplace];
			
			if ( (*routine) >> 6 == 2 )// no route
			{
				(*routine) = ((*routine) & 0x3f) + 0x40;// current route is alternative linkset 
				primitive_to_userpart(nw,mtp3_para->nw[nw].routing[spplace].dpc,AVAILABLE);
			}
			{
				if (Nlinkset_status(*routine) == LS_AVAILABLE)
					(*routine) = ((*routine) & 0x3f);	// current route is normal linkset 
				else if (Alinkset_status(*routine) == LS_AVAILABLE)
					(*routine) = ((*routine) & 0x3f) + 0x40;
				else
					(*routine) = ((*routine) & 0x3f) + 0x80;
			}

			if(0)
			{
				mark_alternative_linkset_available(&mtp3.nw[nw].routine[spplace]);
				routine = (BYTE *)&mtp3.nw[nw].routine[spplace];
			}
			
			if(1)
			if(mtp3ObjState.lk_mtp3[chl] == mtp3_localip && mtp_peer_ip != 0)
			{
				send_route_to_other_plat(mtp3_para->nw[nw].routing[spplace].dpc, 
					nw, 
					sp->routine[spplace], 
					mtp_peer_ip, 
					chl, 
					opc);			
			}
			if(detail_debug_flag)			
			mtp3_debug(MTP3DB_EVENT," <%s:%d> S5 ALS,M3UA update route info, link=%d, sppace=%d, sp->routine=%d", 
				__FUNCTION__, __LINE__,
				chl,
				spplace, sp->routine[spplace]);
			
			if(mtp3ObjState.lk_mtp3[chl] == mtp3_localip && mtp3_para->lk[chl].e1_to_alterMTP3 !=0)
				send_route_to_other_plat(mtp3_para->nw[nw].routing[spplace].dpc, nw, sp->routine[spplace], mtp3_para->lk[chl].e1_to_alterMTP3, chl, opc);			
		}
	}
//	if ((mtp3.nw[nw].routine[dpc_index] & 0x0f) == 0x0a)// all road unavailable
//			mark_dstSP_inaccessible(&mtp3.nw[nw].routine[dpc_index]);
//	hmrt_tfrc_update_routing_tables(dpc_index,nw);

}

int m3ua_ssnm_update_route(xua_ssnm_cmd *p_ssnm)
{
	BYTE ssnm_type,nw;
	WORD link;
	DWORD dpc;
	network	*sp;
	WORD	nls=MAX_LS;
	WORD	als=MAX_LS;
	ls_info	*ls;
	int		i;
	WORD lsno,spplace;
	
	if(p_ssnm == NULL)
		return -1;

	ssnm_type = p_ssnm->type;
	link = p_ssnm->link;
	lsno = mtp3_para->lk[link].e1_to_linkset;
	if ( lsno >= MAX_LS )
	{
		mtp3_debug(MTP3DB_EVENT,"m3ua link %d recv ssnm command, but linkset is error",link);
		return -1;
	}
	nw = mtp3_para->ls_pro[lsno].nw_id;
	ls = &mtp3.ls[lsno];
	sp = &mtp3.nw[nw];

	dpc = p_ssnm->aff_pc;
	for ( i=0; i<(ls->influ_dstnum_asNLS % MAX_LS_DPC_ADD1); i++ )
	{
			spplace = ls->influ_dstplace_intable_asNLS[i];
			if(mtp3_para->nw[nw].routing[spplace].dpc == dpc)
			{
				nls = lsno;
				break;
			}
			spplace = MAX_ROUTE;
	}
	
	if(nls != lsno)
	{
			for ( i=0; i<(ls->influ_dstnum_asALS % MAX_LS_DPC_ADD1); i++ )
			{
					spplace = ls->influ_dstplace_intable_asALS[i];
					if(mtp3_para->nw[nw].routing[spplace].dpc == dpc)
					{
						nls = lsno;
						break;
					}
					spplace = MAX_ROUTE;
			}
	}

	switch(ssnm_type)
	{
		case 1://SSNM_DUNA:
			mtp3_debug(MTP3DB_EVENT,"m3ua link %d recv SSNM_DUNA dpc=%ld",link,dpc);
			if(spplace >= MAX_ROUTE)
			{
				return -1;
			}
			if (nls == lsno)
				mark_normal_linkset_unavailable(&sp->routine[spplace]);
			else if (als == lsno)
				mark_alternative_linkset_unavailable(&sp->routine[spplace]);
			mtp3_debug(MTP3DB_EVENT,"\33[31mM3UA Link %d DPC=%ld out of service,linkset = %d \33[0m",link,dpc, lsno);			
			break;
		case 2://SSNM_DAVA:
			mtp3_debug(MTP3DB_EVENT,"m3ua link %d recv SSNM_DAVA dpc=%ld",link,dpc);
			if(spplace >= MAX_ROUTE)
			{
				return -1;
			}
			if (nls == lsno)
				mark_normal_linkset_available(&sp->routine[spplace]);
			else if (als == lsno)
				mark_alternative_linkset_available(&sp->routine[spplace]);
			mtp3_debug(MTP3DB_EVENT,"\33[32mM3UA Link %d DPC=%ld in service,linkset = %d \33[0m",link,dpc, lsno);			
			break;
		case 3://SSNM_DAUD:
			mtp3_debug(MTP3DB_EVENT,"m3ua link %d recv SSNM_DAUD dpc=%ld",link,dpc);
			if(mtp3_check_dpc_equal_to_opc(nw, dpc))
			{
				mtp3_debug(MTP3DB_EVENT,"m3ua link %d send SSNM_DAVA dpc=%ld",link,dpc);
				send_command_to_m3ua(link, 2, M3UA_SSNM_CMD, 0, dpc);//SSNM_DAVA
			}
			else 
			{// fix me to support M3UA STP 
				mtp3_debug(MTP3DB_EVENT,"m3ua link %d send SSNM_DUNA dpc=%ld",link,dpc);
				send_command_to_m3ua(link, 1, M3UA_SSNM_CMD, 0, dpc);//SSNM_DUNA
			}
			break;
		case 6://SSNM_DRST:
		case 5://SSNM_DUPU:
		case 4://SSNM_SCON:
		default :
			mtp3_debug(MTP3DB_EVENT,"m3ua link %d recv ssnm_type=%d",link,ssnm_type);
			return -1;
	}

	if(spplace >= MAX_ROUTE)
	{
		return -1;
	}
	hmrt_tfrc_update_routing_tables(spplace, nw);
	if((sp->routine[spplace] & 0x80) == 0x80)
		primitive_to_userpart(nw,mtp3_para->nw[nw].routing[spplace].dpc,UNAVAILABLE);
	else 
		primitive_to_userpart(nw,mtp3_para->nw[nw].routing[spplace].dpc,AVAILABLE);

	if(1)
	if(mtp3ObjState.lk_mtp3[link] == mtp3_localip && mtp_peer_ip != 0)
	{
		send_route_to_other_plat(mtp3_para->nw[nw].routing[spplace].dpc, 
			nw, 
			sp->routine[spplace], 
			mtp_peer_ip, 
			link, 
			mtp3_para->nw[nw].routing[spplace].opc);
	}
	
	if(mtp3ObjState.lk_mtp3[link] == mtp3_localip && mtp3_para->lk[link].e1_to_alterMTP3 !=0)
		send_route_to_other_plat(mtp3_para->nw[nw].routing[spplace].dpc, nw, sp->routine[spplace], mtp3_para->lk[link].e1_to_alterMTP3, link, mtp3_para->nw[nw].routing[spplace].opc);

	return 1;
}
	
int m3ua_updateStatus(WORD chl, BYTE new_l2_state,BYTE command, DWORD rc, BYTE rc_status)
{
	WORD	ls_t;
	BYTE	nw;
	int j, sls, lsx16;
	ls_info	*ls;
	int		set_unaccessable = 0 ;

	/*
	if ((mtp3ObjState.lk_configured[chl] == PARA_NOT_CONFIGURED) ||
 		(mtp3ObjState.lk_mtp3[chl] != mtp3_localip))
		return 0;
	
	*/
      rc_timer = 195+(mtp2_systemid%2)*5;
	
	if (mtp3ObjState.lk_configured[chl] == PARA_NOT_CONFIGURED)
		return 0;

	ls_t = mtp3_para->lk[chl].e1_to_linkset;
	if(mtp3ObjState.link_l1_state[chl] == 0 && mtp3ObjState.link_l2_state[chl]!=0)
	{
		mtp3ObjState.link_l2_state[chl] = 0;//reset l2 state
	}	
	if (ls_t >= MAX_LS)
		return 0;
	lsx16 = ls_t<<4;
	ls = &mtp3.ls[ls_t];
	nw =  mtp3_para->ls_pro[ls_t].nw_id&3;
	 ls->links_available_t  = scan_ls_link_available(ls_t);


	if(detail_debug_flag)
	{
		mtp3_debug(MTP3DB_ERROR,"m3ua_updateStatus, link=%d, l2_state=%d, command=%d, rc=%d, rc_status=%d", 
				chl,	new_l2_state, command, rc, rc_status);
		mtp3_debug(MTP3DB_ERROR,"old, l2 state=%d, l3_state=%d links available_t=%d", 
				mtp3ObjState.link_l2_state[chl], mtp3ObjState.link_l3_state[chl], ls->links_available_t);
	}
	
	if (new_l2_state != mtp3ObjState.link_l2_state[chl])
	{
		if(detail_debug_flag)
		{
			mtp3_debug(MTP3DB_ERROR,"m3ua_updateStatus, link=%d, l2_state=%d, command=%d, rc=%d, rc_status=%d", 
					chl,	new_l2_state, command, rc, rc_status);
			mtp3_debug(MTP3DB_ERROR,"old, l2 state=%d, l3_state=%d links available_t=%d", 
					mtp3ObjState.link_l2_state[chl], mtp3ObjState.link_l3_state[chl], ls->links_available_t);
		}
		
		if (new_l2_state == MTP2_STATE_WORKING)
		{
			current_measure->lk_measure1[chl][2]++;
			mtp3_debug(MTP3DB_EVENT,"m3ua link %d L2 in service",chl);
			mtp3_debug(MTP3DB_EVENT,"\33[32mM3UA Link %d L3 in service,linkset = %d \33[0m",chl, ls_t);			
			if ( ls->links_available_t > 0 )/* WITHIN LS */
			{
				for ( j=0; j<16; j++ )
				{
					sls = lsx16+j;
					if ( (ls_sls[sls] != chl)	&&
						 (sls_to_link[sls] == chl)	)
						ls_sls[sls] = chl;
				}
			}
			else
			{
				current_active_ls_num++;
				current_measure->ls_measure[ls_t][2]++;/* STOP of link set failure */
				memset(&ls_sls[lsx16],chl,16);
			}
			if (mtp3ObjState.lk_mtp3[chl] == mtp3_localip)
			{
				mtp3_send_mtp2_alarm(8+chl,0);
			}	
			set_heartbeat(ALARM_LINK_AVAILABLE, chl);
			set_heartbeat(ALARM_LS_AVAILABLE,ls_t);
			mtp3_send_alarm(ls_t+MTP3_LINKSET_COMPONENT,0);
			//mtp3ObjInput.lsac_input_from_l2[chl] = LSAC_L2_IN_SERVICE;

			//hmrt_tcbc_update_routing_tables(chl);

	    		mtp3ObjState.link_l1_state[chl] = 1;
    			mtp3ObjState.link_l2_state[chl] = MTP2_STATE_WORKING;
    			mtp3ObjState.link_l3_state[chl] = AVAILABLE;
       		mtp3ObjState.lsac_state[chl] = LSAC_ACTIVE_STATE;
       		mtp3ObjState.sltc_state[chl] = SLTC_RUNNING_STATE;
       		mtp3ObjState.tlac_state[chl] = TLAC_AVAILABLE_STATE;
			
			//ls->links_available++;
			/*				
			if (mtp3.ls[ls_t].links_available == 0)
       			m3ua_upd_route_status(chl, 1, rc, rc_status);
			hmrt_tcbc_update_routing_tables(chl);

       		*/
       		//if(ls->links_available_t  == 0)
       			m3ua_upd_route_status(chl, rc, 5, 1);
	
			mtp3.ls[ls_t].links_available ++;

			 ls->links_available_t  = scan_ls_link_available(ls_t);

			if(ls->links_available_t == 1)
			{
				if (mtp3ObjState.lk_mtp3[chl] != mtp3_localip)
					ls->send_asp_ac_link_id = chl;
			}
				
			if(0)
			{
				if(ls->links_available_t== 1)
				{
					if(ls->send_asp_ac_link_id == 0x00 || ls->send_asp_ac_link_id == 0xffff )
		 			{//for override mode
						ls->send_asp_ac_link_id = chl;

						m3ua_set_link_rc_to_m2ua(chl);
						
						send_command_to_m3ua(chl, 1,M3UA_RC_CMD , rc, 0);			
						if(detail_debug_flag)
								mtp3_debug(MTP3DB_EVENT,"<%s:%d> M3UA send RC_CMD, link=%d", 
											__FUNCTION__, __LINE__,
											chl);
						
					}
				}
			}
			
    	   		//mtp3ObjState.lk_mtp3[chl] = mtp3_localip;
		}
		else if (mtp3ObjState.link_l2_state[chl] == MTP2_STATE_WORKING)
		{
			local_change_over[chl]++;
			mtp3_debug(MTP3DB_EVENT,"m3ua link %d L2 out of service",chl);
			mtp3_debug(MTP3DB_EVENT,"\33[31mM3UA Link %d L3 out of service,Linkset %d out of service\33[0m",chl,ls_t);
			hmrt_tcoc_update_routing_tables(chl);
			set_heartbeat(ALARM_LINK_UNAVAILABLE,chl);			
			if (mtp3ObjState.lk_mtp3[chl] == mtp3_localip)
			{
//				mtp3_send_alarm(ls_t+MTP3_LINKSET_COMPONENT,1);
				mtp3_send_mtp2_alarm(8+chl,M2UAALARM_SCTP_Failure);
			}
			
			//mtp3ObjInput.lsac_input_from_l2[chl] = LSAC_L2_OUT_OF_SERVICE;
			//mtp3ObjInput.sltc_input[chl] = SLTC_STOP;
			//sltc_proc(chl);
			mtp3ObjState.link_l1_state[chl] = 0;
			mtp3ObjState.link_l2_state[chl] = 0;
			mtp3ObjState.link_l3_state[chl] = 0;
   			mtp3ObjState.lsac_state[chl] = 0;
    			mtp3ObjState.sltc_state[chl] = 0;
    			mtp3ObjState.tlac_state[chl] = 0;
			
			memset(mtp3.ls[ls_t].links_nls_asp_ac_send_flag, 0x00, sizeof(BYTE)*(MAX_ROUTE+1));
			memset(mtp3.ls[ls_t].links_als_asp_ac_send_flag, 0x00, sizeof(BYTE)*(MAX_ROUTE+1));

			if (mtp3.ls[ls_t].links_available > 0)
				mtp3.ls[ls_t].links_available --;
			
			 if(ls->send_asp_ac_link_id == chl)
			 	ls->send_asp_ac_link_id = 0xFFFF;
			 
			 ls->links_nls_asp_ac_send_flag[chl] = 0;
			 
			 ls->links_available_t  = scan_ls_link_available(ls_t);
			
			if(mtp3.ls[ls_t].links_available_t == 0)	
				m3ua_upd_route_status(chl, rc, 0, 1);

			set_unaccessable = 1;

			/*
			if (mtp3.ls[ls_t].links_available_t > 0)
				mtp3.ls[ls_t].links_available_t --;
			*/

		}

	}
	if(new_l2_state==0)//fixed m3ua dual handling
	{
		mtp3ObjState.link_l3_state[chl] = 0;
   		mtp3ObjState.lsac_state[chl] = 0;
		 ls->links_available_t  = scan_ls_link_available(ls_t);

		if(m2ua_get_traffic_mode_type()==0)
		{
			if(ls->send_asp_ac_link_id == chl)
		 		ls->send_asp_ac_link_id = 0xFFFF;
		}
		
		if( set_unaccessable == 0)
		{
			if(mtp3.ls[ls_t].links_available_t == 0)	
				m3ua_upd_route_status(chl, rc, 0, 1);
		}
	}
	if(command==1)//rc status
	{
   		m3ua_upd_route_status(chl, rc, rc_status, 0);
	}

//	m3ua_check_route_status(chl);

	return 1;
}

int GetM3uaMsg(ulong port)
{
	xua_m3ua_msg *msgptr = NULL;
	xua_lm_lk *lm_lk_ptr = NULL;
	xua_rc_cmd *rc_cmd_ptr = NULL;
	xua_ssnm_cmd *ssnm_cmd_ptr = NULL;
	BYTE nw,dpc_equal_to_opc,ssf;
	BYTE new_l2_state;
	BYTE rc_status,  db_type;
	DWORD rc, chl;
	WORD m3ua_msg_len;

	if(!get_m3ua_msg(&mtp3_m3ua_msg))
	{
		msgptr = &mtp3_m3ua_msg->msg.m3ua;
		lm_lk_ptr = &mtp3_m3ua_msg->msg.lm_lk;	
		rc_cmd_ptr = &mtp3_m3ua_msg->msg.rc_cmd;
		ssnm_cmd_ptr = &mtp3_m3ua_msg->msg.ssnm_cmd;
/*			if( mtp3_send_netcap && ( (mtp3_m3ua_msg->sio & 0xF0 ) != 0xF0 ) )
			{
			        int pclen ;
			        sio = mtp3_m3ua_msg->sio;
			        nw = sio >> 6;
			    	pclen = pc_length(nw);

			    	if ( pclen == MTP3_24BIT_PC ) //ansi
			    	{
			    	    NcMtp3Send ( &mtp3_m3ua_msg->sio
			    	                 , ntohs(mtp3_m3ua_msg->len), 1 );
			    	}
			    	else if ( pclen == MTP3_14BIT_PC ) //ITU
			    	{
			    	    NcMtp3Send (  &mtp3_m3ua_msg->sio
			    	                 , ntohs(mtp3_m3ua_msg->len), 0 );
			    	}
			}
*/

		if(mtp3_m3ua_msg->msg_class == M3UA_MGMT_CMD)
		{

				chl = lm_lk_ptr->link;//???
				new_l2_state = lm_lk_ptr->opercode;
				if(new_l2_state)
				m3ua_updateStatus(chl, new_l2_state, 0, 0 ,0);
				mtp3_debug(MTP3DB_PRIMITIVE_MSG,"get M3UA link[%d], state=%d, heartbeat from %lx", chl, new_l2_state, msgSourceIP);
				mtp3_showbuf(MTP3DB_PRIMITIVE_MSG,(BYTE *)mtp3_m3ua_msg,ntohs(lm_lk_ptr->len)+4);
				
				return 0;

		}
		else if(mtp3_m3ua_msg->msg_class == M3UA_RC_CMD)
		{
				chl = rc_cmd_ptr->link;//???
				rc_status = rc_cmd_ptr->opercode;
				rc = rc_cmd_ptr->rc;
				m3ua_updateStatus(chl, 5, 1, rc, rc_status);
				mtp3_debug(MTP3DB_PRIMITIVE_MSG,"get M3UA rc heartbeat from %lx",msgSourceIP);
				mtp3_showbuf(MTP3DB_PRIMITIVE_MSG,(BYTE *)mtp3_m3ua_msg,ntohs(rc_cmd_ptr->len)+4);
				return 0;

		}
		else if(mtp3_m3ua_msg->msg_class == M3UA_SSNM_CMD)
		{
				m3ua_ssnm_update_route(ssnm_cmd_ptr);
				mtp3_debug(MTP3DB_PRIMITIVE_MSG,"get M3UA ssnm message from %lx",msgSourceIP);
				mtp3_showbuf(MTP3DB_PRIMITIVE_MSG,(BYTE *)mtp3_m3ua_msg,ntohs(ssnm_cmd_ptr->len)+4);
				return 0;

		}
		else if(mtp3_m3ua_msg->msg_class == M3UA_MAUP_MSG)// M3uaMsg
		{
				nw = msgptr->ni;
				ssf = msgptr->si;		
				dpc_equal_to_opc = mtp3_check_dpc_equal_to_opc(msgptr->ni, msgptr->dpc);
				m3ua_msg_len = ntohs(msgptr->len)+20+1;
				//if (msgdpc != mtp3_para->nw[nw].opc24)/* STP */
				if (!dpc_equal_to_opc) //STP
				{
					mtp3_debug(MTP3DB_ERROR,"mtp3<==m3ua, dpc=%lx!=local opc, len=%d!", msgptr->dpc, m3ua_msg_len);
					mtp3_showbuf(MTP3DB_ERROR,(BYTE *)mtp3_m3ua_msg, m3ua_msg_len);
					return 1;//not support STP
/*
					sls = msgprt->sls;//msgptr[10] & 0x0f;
					outlink = check_outbound_route(nw,msgdpc,sls);
					if (outlink >= 0)
					{
						if (ip_port == M2UA_PORT)
						{
							memcpy(mtp3_iprt.io_msg.msgContent, msgptr, len);
							msgptr = mtp3_iprt.io_msg.msgContent;
						}
						mtp3_Trans_stpMsg(msgptr,outlink,pc_len);
						return 1;
						}
*/
					
				}
				else
				{
					switch(msgptr->si)
					{
						case SCCP_SIO:
							if ( (S_shm_ptr->MS_Buf.WSub+1) == S_shm_ptr->MS_Buf.RSub)// buffer overflow
							{
								mtp3.nw[nw].flow.MtoU_throwed[0]++;
								break;
							}
							m3ua_send_to_sccp(msgptr);
							db_type = MTP3DB_SCCPMSG;
							mtp3_debug(db_type,"SCCP<==M3UA,NW=%x,SIO=%x,SPC(%lx->%lx),link=%d",msgptr->ni,msgptr->si,msgptr->opc,msgptr->dpc,msgptr->link);
							break;
						case BICC_SIO:
							if ( (B_shm_ptr->MI_Buf.WSub+1) == B_shm_ptr->MI_Buf.RSub)// buffer overflow
							{
								mtp3.nw[nw].flow.MtoU_throwed[2]++;
								break;
							}
							m3ua_send_to_bicc(msgptr);
							db_type = MTP3DB_BICCMSG;
							mtp3_debug(db_type,"BICC<==M3UA,NW=%x,SIO=%x,SPC(%lx->%lx),link=%d",msgptr->ni,msgptr->si,msgptr->opc,msgptr->dpc,msgptr->link);
							break;
						case ISUP_SIO:
							if ( (I_shm_ptr->MI_Buf.WSub+1) == I_shm_ptr->MI_Buf.RSub)// buffer overflow
							{
								mtp3.nw[nw].flow.MtoU_throwed[2]++;
								break;
							}
							m3ua_send_to_isup(msgptr);
							db_type = MTP3DB_ISUPMSG;
							mtp3_debug(db_type,"ISUP<==M3UA,NW=%x,SIO=%x,SPC(%lx->%lx),link=%d",msgptr->ni,msgptr->si,msgptr->opc,msgptr->dpc,msgptr->link);
							break;
						case TUP_SIO:
							if ( (T_shm_ptr->MT_Buf.WSub+1) == T_shm_ptr->MT_Buf.RSub)// buffer overflow
							{
								mtp3.nw[nw].flow.MtoU_throwed[1]++;
								break;
							}
							m3ua_send_to_tup(msgptr);
							db_type = MTP3DB_TUPMSG;
							mtp3_debug(db_type,"TUP<==M3UA,NW=%x,SIO=%x,SPC(%lx->%lx),link=%d",msgptr->ni,msgptr->si,msgptr->opc,msgptr->dpc,msgptr->link);
							break;

						default:
							db_type = MTP3DB_ERROR;
							mtp3_debug(db_type,"MTP3<==M3UA,NW=%x,SIO=%x,SPC(%lx->%lx),link=%d",msgptr->ni,msgptr->si,msgptr->opc,msgptr->dpc,msgptr->link);
							mtp3.nw[msgptr->ni].flow.ItoM_throwed[msgptr->si-1]++;
							break;

					}

					mtp3_showbuf(db_type, (BYTE *)mtp3_m3ua_msg, m3ua_msg_len);
				}
			}
		}
	return 1;
}


int send_command_to_m3ua(WORD link, BYTE command, BYTE xua_msg_class, DWORD rc, DWORD aff_pc)
{
	char charCmd[32];	
	static int rc_cmd_counter=0, total_cmd_counter=0;
	
	if(0)
	{
		if(rc_cmd_counter  < 5 && total_cmd_counter++ < 100)
		{
			char buf[128];
			
			sprintf(buf, "link=%d, cmd=%d, xmc=%d", link, command, xua_msg_class);
			pub_print_traceback(buf);
		}
	}
	
	if(xua_msg_class == M3UA_RC_CMD)
	{
		rc_cmd_counter ++;
		mtp3_iprt.io_msg.msgLength = 5+1+4+1;
		mtp3_iprt.io_msg.msgContent[0] = xua_msg_class;
		mtp3_iprt.io_msg.msgContent[2] = link>>8;
		mtp3_iprt.io_msg.msgContent[1] = link&0xff;
		mtp3_iprt.io_msg.msgContent[3] = 0;
		mtp3_iprt.io_msg.msgContent[4] = 7;
		mtp3_iprt.io_msg.msgContent[9] = command;
		memcpy(&mtp3_iprt.io_msg.msgContent[5], &rc, 4);

		sprintf(charCmd,"M3UA_ASP_Active");
				
	}else if(xua_msg_class == M3UA_MGMT_CMD)
	{
		mtp3_iprt.io_msg.msgLength = 5+1+1;
		mtp3_iprt.io_msg.msgContent[0] = xua_msg_class;
		mtp3_iprt.io_msg.msgContent[2] = link>>8;
		mtp3_iprt.io_msg.msgContent[1] = link&0xff;
		mtp3_iprt.io_msg.msgContent[3] = 0;
		mtp3_iprt.io_msg.msgContent[4] = 3;
		mtp3_iprt.io_msg.msgContent[5] = ((mtp3ObjState.lk_mtp3[link] >> 16) & 0xff)-32;// 172.18.x+32.1
		mtp3_iprt.io_msg.msgContent[6] = command;

		switch (command)
		{
			case MTP2_DEACTIVE_LINK:
				sprintf(charCmd,"M3UA_DEACTIVE_LINK");
				break;
			case MTP3_M3UA_ENABLE:
				sprintf(charCmd,"M3UA_ACTIVE_LINK");
				break;
			case MTP3_M3UA_DISABLE:
				sprintf(charCmd,"M3UA_DISABLE_LINK");
				break;
			default:
				break;
		}
	}
	else if(xua_msg_class == M3UA_SSNM_CMD)
	{
		mtp3_iprt.io_msg.msgLength = 10;
		mtp3_iprt.io_msg.msgContent[0] = xua_msg_class;
		mtp3_iprt.io_msg.msgContent[2] = link>>8;
		mtp3_iprt.io_msg.msgContent[1] = link&0xff;
		mtp3_iprt.io_msg.msgContent[3] = 0;
		mtp3_iprt.io_msg.msgContent[4] = 7;
		mtp3_iprt.io_msg.msgContent[5] = command;
		memcpy(&mtp3_iprt.io_msg.msgContent[6], &aff_pc, 4);
	}
	else 
		return 0;
	mtp3_debug(MTP3DB_PRIMITIVE_MSG,"MTP3 send command %s to m3ua link %d",charCmd,link);
	mtp3_showbuf(MTP3DB_PRIMITIVE_MSG,&mtp3_iprt.io_msg.msgContent[0],mtp3_iprt.io_msg.msgLength);
	put_m3ua_msg((xua_up_msg_t *) mtp3_iprt.io_msg.msgContent);
	return 1;
}

void deactive_m3ua_lk(WORD link)
{
	if ((MTP3_LINK_TYPE(link) == LKTYPE_M3UA) && 	// M3UA
		(mtp3_para->lk[link].admin_state& 0x01))
	{
		mtp3_debug(MTP3DB_EVENT,"m3ua link %d Deactive by MNG",link);
		send_command_to_m3ua(link, MTP3_M3UA_DISABLE,M3UA_MGMT_CMD,0,0);
		m3ua_updateStatus(link, 0, 0, 0 ,0);

	}
}

void m3ua_set_link_rc_to_m2ua(int linkno)
{
	int i;
	WORD lsno, spplace;
	BYTE  nw;
	DWORD rc;
	network	*sp;
	ls_info	*ls;

	lsno = mtp3_para->lk[linkno].e1_to_linkset;
	if (lsno >= MAX_LS)
		return;

	ls = &mtp3.ls[lsno];
	nw = mtp3_para->ls_pro[lsno].nw_id;
	sp = &mtp3.nw[nw];
	
	for ( i=0; i<(ls->influ_dstnum_asNLS % MAX_LS_DPC_ADD1); i++ )
	{
		spplace = ls->influ_dstplace_intable_asNLS[i];
		rc = mtp3_para->nw[nw].routing[spplace].rc;
		m2ua_set_sg_rc(linkno, rc);
	}

}

void check_m3ua_link_status(int force_flag)
{
	int link,i;
	WORD lsno, spplace;
	BYTE  nw;
	DWORD rc;
	network	*sp;
	ls_info	*ls;
	static int link_timer=0;
	int check_timer = (  mtp2_systemid  * 30 + 400);
	int send_asp_ac_flag = 0;
	
	if(rc_timer >= check_timer || force_flag)//2s
	{
		rc_timer = 0;
		for(link=0;link<MAX_LK; link++)
		{

//			if(MTP3_LINK_TYPE(link) == LKTYPE_M3UA && (mtp3_para->lk[link].admin_state& 1)&&(check_if_local_ip(mtp3ObjState.lk_mtp3[link] )) ) //mtp3_localip))
			if(MTP3_LINK_TYPE(link) == LKTYPE_M3UA && (mtp3_para->lk[link].admin_state& 1)&&(mtp3ObjState.lk_mtp3[link] == mtp3_localip))			
			{
				if(mtp3ObjState.link_l3_state[link] == AVAILABLE)
				{
					lsno = mtp3_para->lk[link].e1_to_linkset;
					if (lsno >= MAX_LS)
						return;
					ls = &mtp3.ls[lsno];
					nw = mtp3_para->ls_pro[lsno].nw_id;
					sp = &mtp3.nw[nw];
					 ls->links_available_t  = scan_ls_link_available(lsno);

					send_asp_ac_flag = 0;						

					for ( i=0; i<(ls->influ_dstnum_asNLS % MAX_LS_DPC_ADD1); i++ )
					{
						spplace = ls->influ_dstplace_intable_asNLS[i];
						rc = mtp3_para->nw[nw].routing[spplace].rc;

						m2ua_set_sg_rc(link, rc);

						if(m2ua_get_traffic_mode_type()==0)
						{
							/*
							if(ls->links_nls_asp_ac_send_flag[spplace] == 1 )
							{
								if(ls->links_available_t == 1)
								{
									if(ls->send_asp_ac_link_id != link)
										send_asp_ac_flag = 1;								
								}
								else
									break;
							}
							*/
							if (sp->m3ua_rc_status[spplace]!=5)/*normal route unavailable */
							{
								if(ls->links_nls_asp_ac_send_flag[spplace] != 1 )
								{
									send_asp_ac_flag = 1;
								}
								if(ls->links_available_t >1)
								{
									send_asp_ac_flag = 0;
								}

							}
							else if(ls->links_available_t == 1)
							{
								if(ls->send_asp_ac_link_id != link)
								{
									send_asp_ac_flag = 1;								
								}
							}
							if(send_asp_ac_flag == 0)
							{
								//ls->send_asp_ac_link_id = link;	//
								if(0)
								{
									if(detail_debug_flag)
									mtp3_debug(MTP3DB_EVENT,"<%s:%d> M3UA send RC_CMD, link=%d, total links=%d, sppace=%d, sp->routine=%d, act link=%d", 
												__FUNCTION__, __LINE__,
												link, 
												ls->links_available_t,
												spplace, 
												sp->routine[spplace],
												ls->send_asp_ac_link_id);

								}
								
							}
							else
							{
								if(ls->links_nls_asp_ac_send_flag[link] == 1)
									send_asp_ac_flag = 0;
							}
						}
						else
						{
							if(0)
							mtp3_debug(MTP3DB_EVENT,"<%s:%d> link=%d, sppace=%d, sp->routine=%d, rc_status=%d, lk_asp_ac=%d", 
										__FUNCTION__, __LINE__,
										link, 
										spplace, 
										sp->routine[spplace],
										sp->m3ua_rc_status[spplace],
										ls->links_nls_asp_ac_send_flag[link]);

						
							if(sp->m3ua_rc_status[spplace]!=5 || ls->links_nls_asp_ac_send_flag[link] == 0 )
							{		
								send_asp_ac_flag = 1;
								/*
								ls->links_nls_asp_ac_send_flag[spplace] = 0x01;
								ls->send_asp_ac_link_id = link;
								send_command_to_m3ua(link, 1,M3UA_RC_CMD , rc, 0);
								*/
							}
						}

						if(send_asp_ac_flag)
						{
							ls->links_nls_asp_ac_send_flag[link] = 0x01;
							ls->send_asp_ac_link_id = link;		
							
							send_command_to_m3ua(link, 1,M3UA_RC_CMD , rc, 0);			
							if(detail_debug_flag)
							mtp3_debug(MTP3DB_EVENT,"<%s:%d> M3UA send RC_CMD, link=%d, total links=%d, sppace=%d, sp->routine=%d, rc=%d", 
										__FUNCTION__, __LINE__,
										link, 
										ls->links_available_t,
										spplace, 
										sp->routine[spplace],
										sp->m3ua_rc_status[spplace]);

							break;
							
						}

						/*
						if(m2ua_get_traffic_mode_type()==0)
						{

							if (sp->m3ua_rc_status[spplace]!=5)//normal route unavailable
							{
								ls->links_nls_asp_ac_send_flag[spplace] = 0x01;
							
								send_command_to_m3ua(link, 1,M3UA_RC_CMD , rc, 0);
							}
						}
						else
						{
							if(sp->m3ua_rc_status[spplace]!=5 || ls->links_nls_asp_ac_send_flag[spplace] == 0x00)
							{
								ls->links_nls_asp_ac_send_flag[spplace] = 0x01;
							
								send_command_to_m3ua(link, 1,M3UA_RC_CMD , rc, 0);
							}
						}
						*/
					}
					for ( i=0; i<(ls->influ_dstnum_asALS % MAX_LS_DPC_ADD1); i++ )
					{
						spplace = ls->influ_dstplace_intable_asALS[i];
						rc = mtp3_para->nw[nw].routing[spplace].rc;

						/*
						if(m2ua_get_traffic_mode_type()==0)
						{

							if (sp->m3ua_rc_status[spplace]!=5)//alter route unavailable 
							{
								if(ls->links_als_asp_ac_send_flag[spplace] == 0x00)
								{
									ls->links_als_asp_ac_send_flag[spplace] = 0x01;
							
									send_command_to_m3ua(link, 1, M3UA_RC_CMD, rc, 0);

									mtp3_debug(MTP3DB_EVENT,"<%s:%d> M3UA send RC_CMD, link=%d, sppace=%d, sp->routine=%d", 
											__FUNCTION__, __LINE__,
											link, spplace, sp->routine[spplace]);
								}
							}
						}
						else
						{
							if(sp->m3ua_rc_status[spplace]!=5 || ls->links_als_asp_ac_send_flag[spplace] == 0x00)												
							{
								ls->links_als_asp_ac_send_flag[spplace] = 0x01;
						
								send_command_to_m3ua(link, 1, M3UA_RC_CMD, rc, 0);

								mtp3_debug(MTP3DB_EVENT,"<%s:%d> M3UA send RC_CMD, link=%d, sppace=%d, sp->routine=%d", 
										__FUNCTION__, __LINE__,
										link, spplace, sp->routine[spplace]);

							}
						}
						*/
					}
				}
				else
				{
					lsno = mtp3_para->lk[link].e1_to_linkset;
					if (lsno >= MAX_LS)
						return;
					ls = &mtp3.ls[lsno];
				
					ls->links_nls_asp_ac_send_flag[link] = 0x00;
					ls->send_asp_ac_link_id = 0x00;		
				
				}
			}
		}
	}
	if(link_timer>=1000)//10s
	{
		link_timer = 0;
		for(link=0;link<MAX_LK; link++)
		{
			if(MTP3_LINK_TYPE(link) == LKTYPE_M3UA && (mtp3_para->lk[link].admin_state& 1) &&(mtp3ObjState.lk_mtp3[link] == mtp3_localip))
			{
				if(mtp3ObjState.link_l3_state[link] == UNAVAILABLE || mtp3ObjState.link_enable_sent_flag[link] == 0)
				{
					mtp3ObjState.link_enable_sent_flag[link] = 1;
					send_command_to_m3ua(link, MTP3_M3UA_ENABLE,M3UA_MGMT_CMD,0, 0);

					rc_timer = 100;
				}
			}
/*			if(MTP3_LINK_TYPE(link) == LKTYPE_M3UA && mtp3ObjInput.lsac_input_from_mgmt[link] == LSAC_MGMT_DEACTIVATE_LINK)
			{
//				mtp3_debug(MTP3DB_EVENT,"m3ua link %d Deactive by other plat MNG",link);
//				send_command_to_m3ua(link, MTP3_M3UA_DISABLE,M3UA_MGMT_CMD,0);
				deactive_m3ua_lk(link);
				mtp3ObjInput.lsac_input_from_mgmt[link] = LSAC_MGMT_ACTIVATE_LINK;
				
			}
*/
		}
	}
	link_timer++;
	rc_timer++;
}


void m3ua_timer()
{
	check_m3ua_link_status(0);
}

void send_mtp_msg(int outlink, BYTE	*msgptr)
{
	int		linkset;
	ls_info	*ls;
	ls_para *ls_pro=NULL;
	BYTE	nw;
	ulong	dst_ip;
	long	opc,dpc;
	long	route_mark;
	BYTE	sls;
	BYTE	pclen;
	WORD len;
	BYTE	ssf;
	BYTE	debugtype=0;
	xua_up_msg_t *m3ua_ptr=NULL;

	if(msgptr == NULL)
	{
		return;
	}
	m3ua_ptr = (xua_up_msg_t *)msgptr;
	ssf = msgptr[3] & 0x0f;
	linkset = mtp3_para->lk[outlink].e1_to_linkset;
	ls = &mtp3.ls[linkset];
	ls_pro = &mtp3_para->ls_pro[linkset];
	nw = ls_pro->nw_id;
	pclen = pc_length(nw);
	if ( ls_pro->loopback_opt != 0 )/* this linkset is loop back linkset */
	{
		if ( pclen == MTP3_24BIT_PC )
		{
			opc = mtp3_para->nw[nw].opc24;
			memcpy( &msgptr[5],&opc,3);/* change msg's dpc to opc */
		}
		else
		{
			opc = mtp3_para->nw[nw].opc14;
			memcpy( (BYTE*)&route_mark,&msgptr[5],4);
			sls = (route_mark >> 28) & 0xf;
			route_mark = (sls << 28)+(opc << 14)+opc;
			memcpy(&msgptr[5],&route_mark,4);
		}
	}

	if (ssf > 1)
	{
		ssf--;
		debugtype = MTP_MSG_DOWN;
	}
	else
		debugtype = MTP_SNM_MSG;
//	current_measure->tf_measure1[4][wx5[nw]+ssf]+=len;/* octets */
	current_measure->tf_measure2[4][wx5[nw]+ssf]++;/* MSUs */

//	len = msgptr[1]+2;
	len = (msgptr[2]<<8) + msgptr[3]+4;
	if(len > MAX_SS7_MSG_LEN)
	{
		mtp3_debug(MTP3DB_ERROR,"send_mtp_msg, length longer than %d, len=%d!", MAX_SS7_MSG_LEN, len);
		msgptr[2] = 0;
		len = MAX_SS7_MSG_LEN;
	}
	mtp3_iprt.io_msg.msgLength = len;

	if( mtp3_send_netcap && ( ( msgptr[4] & 0xF0) != 0xF0 ) )
	{
	    if ( pclen == MTP3_24BIT_PC )      //ansi
	    {
	         NcMtp3Send ( &msgptr[4], (msgptr[2]<<8) + msgptr[3], 1 );
	    }
	    else if ( pclen == MTP3_14BIT_PC ) //ITU
	    {
	      	 NcMtp3Send ( &msgptr[4], (msgptr[2]<<8) + msgptr[3], 0 );
	    }
	}

#if _INCLUDE_M2UA
	if (mtp3ObjState.lk_mtp3[outlink] != mtp3_localip)
	{//transfer to remote plat
		dst_ip = mtp3ObjState.lk_mtp3[outlink];
		//dst_ip = (dst_ip << 16) | E1CARD_BASE_IP;
	/* debug show message */
		if (iptrans_msg_flow(msgptr,pclen,debugtype,dst_ip));
	/* debug show message */
//		send_to_mtp2(dst_ip);
		send_to_mtp2_new_struct(dst_ip);
	}
	else if (MTP3_LINK_TYPE(outlink) == LKTYPE_NONE_SIGTRAN)
#endif
	{
		dst_ip = LINK_TO_IP(outlink);
	/* debug show message */
		if (iptrans_msg_flow(msgptr,pclen,debugtype,dst_ip));
	/* debug show message */
		send_to_mtp2(dst_ip);//use old struct send to 8k bload
	}
#if _INCLUDE_M2UA
	else
	{
		if (MTP3_LINK_TYPE(outlink) == LKTYPE_MTP3_LITE)
		{
			/* debug show message */
			dst_ip = mtp3_para->lk[outlink].remote_ip;
			if (iptrans_msg_flow(msgptr,pclen,debugtype,dst_ip));
			/* debug show message */
			if ((msgptr[4] & 0x0f) == 3)
				put_mtp3lite_msg(msgptr);
			return;
		}
		if (MTP3_LINK_TYPE(outlink) == LKTYPE_M3UA)
		{
			dst_ip = mtp3_para->sg[mtp3_para->lk[outlink].e1_to_sg].ip;
			/* debug show message */
			if (iptrans_msg_flow(msgptr,pclen,debugtype,dst_ip));
			/* debug show message */
			if(pclen == MTP3_24BIT_PC)
			{
//					memmove(m3ua_ptr->msg.m3ua.content, msgptr+11+1, len-8-1);
					memmove(m3ua_ptr->msg.m3ua.content, msgptr+11+1, len-6-1);

					dpc = 0;
					opc = 0;
					sls = msgptr[11];
					memcpy(&dpc,&msgptr[5],3);
					memcpy(&opc,&msgptr[8],3);
					m3ua_ptr->msg.m3ua.dpc = dpc;
					m3ua_ptr->msg.m3ua.opc = opc;
					m3ua_ptr->msg_class = M3UA_MAUP_MSG;
					m3ua_ptr->msg.m3ua.ni = nw;
					m3ua_ptr->msg.m3ua.si = msgptr[4] & 0x0f;
//					m3ua_ptr->msg.m3ua.len = ntohs(len - 8 - 1 - 4);    //m3ua_ptr->msg.m3ua.len = ntohs(len - 8-1);    //modify by Jink on 2012-11-01
					m3ua_ptr->msg.m3ua.len = ntohs(len - 6 - 1 - 4);    //m3ua_ptr->msg.m3ua.len = ntohs(len - 8-1);    //modify by Jink on 2012-11-01

					m3ua_ptr->msg.m3ua.mp = 0;
					m3ua_ptr->msg.m3ua.sls = sls;
					m3ua_ptr->msg.m3ua.rc = get_m3ua_rc_by_dpc(nw, m3ua_ptr->msg.m3ua.dpc, m3ua_ptr->msg.m3ua.opc);
			}
			else
			{
					memmove(m3ua_ptr->msg.m3ua.content, msgptr+8+1, len-5-1);
					memcpy( (BYTE*)&route_mark,&msgptr[5],4);
					sls = (route_mark >> 28) & 0xf;
					dpc = route_mark & 0x3fff;
					opc = (route_mark >>14)&0x3fff;
					m3ua_ptr->msg.m3ua.opc = opc;
					m3ua_ptr->msg.m3ua.dpc = dpc;
//					memcpy(&m3ua_ptr->msg.m3ua.opc,&msgptr[7],3);
					m3ua_ptr->msg_class = M3UA_MAUP_MSG;					
					m3ua_ptr->msg.m3ua.ni = nw;
					m3ua_ptr->msg.m3ua.si = msgptr[4] & 0x0f;
					m3ua_ptr->msg.m3ua.len = ntohs(len - 5 - 4);    //m3ua_ptr->msg.m3ua.len = ntohs(len - 5);  //modify by Jink on 2012-11-01
					m3ua_ptr->msg.m3ua.mp = 0;
					m3ua_ptr->msg.m3ua.sls = sls;					
					m3ua_ptr->msg.m3ua.rc = get_m3ua_rc_by_dpc(nw, m3ua_ptr->msg.m3ua.dpc, m3ua_ptr->msg.m3ua.opc);
			}
			m3ua_ptr->msg.m3ua.link = outlink;//???

			put_m3ua_msg((xua_up_msg_t *)msgptr);
			return;
		}
		else
		{
			dst_ip = mtp3_para->sg[mtp3_para->lk[outlink].e1_to_sg].ip;
			/* debug show message */
			if (iptrans_msg_flow(msgptr,pclen,debugtype,dst_ip));
			/* debug show message */
			put_m2ua_msg((m2ua_up_msg_t *)msgptr);
			return;
		}
	}
#endif


}

int get_route_from_other_plat(u32 dpc, u8 nw, long dest_ip, WORD chl, u32 opc)
{
   	mtp3_iprt.io_msg.msgSrcPort = 4950;
	mtp3_iprt.io_msg.msgDstPort = 4950;
	mtp3_iprt.io_msg.msgDstIP = dest_ip;
	mtp3_iprt.io_msg.msgContent[4] = 0x1f;
	mtp3_iprt.io_msg.msgContent[5] = nw;
	memcpy(&mtp3_iprt.io_msg.msgContent[6], &dpc, 4);
	memcpy(&mtp3_iprt.io_msg.msgContent[10], &opc, 4);
	mtp3_iprt.io_msg.msgContent[1] = chl>>8;
	mtp3_iprt.io_msg.msgContent[0] = chl&0xFF;
	mtp3_iprt.io_msg.msgContent[2] = 0;
	mtp3_iprt.io_msg.msgContent[3] = 11;
	mtp3_iprt.io_msg.msgLength = (mtp3_iprt.io_msg.msgContent[2]<<8) + mtp3_iprt.io_msg.msgContent[3]+4;
	iptrDirectSendMsg(mtp3_iprt.io_msg);
	return 1;
}

void get_routes_from_other_plat()
{
	WORD link,i;
	WORD lsno, nw, spplace;
	DWORD dpc, opc;
	network	*sp;
	ls_info	*ls;
	
	for(link=0; link<MAX_LK;link++)
	{
		if(mtp3_para->lk[link].e1_lk_type== LKTYPE_M3UA)
		{
			if(mtp3_para->lk[link].e1_to_mtp3 != mtp3_localip)
			{
					lsno = mtp3_para->lk[link].e1_to_linkset;
						if (lsno >= MAX_LS)
							return;
						ls = &mtp3.ls[lsno];
						nw = mtp3_para->ls_pro[lsno].nw_id;
						sp = &mtp3.nw[nw];

					for ( i=0; i<(ls->influ_dstnum_asNLS % MAX_LS_DPC_ADD1); i++ )
					{
						spplace = ls->influ_dstplace_intable_asNLS[i];
						dpc= mtp3_para->nw[nw].routing[spplace].dpc;
						opc= mtp3_para->nw[nw].routing[spplace].opc;
						get_route_from_other_plat(dpc, nw, mtp3_para->lk[link].e1_to_mtp3, link, opc);						
					}
					for ( i=0; i<(ls->influ_dstnum_asALS % MAX_LS_DPC_ADD1); i++ )
					{
						spplace = ls->influ_dstplace_intable_asALS[i];
						dpc= mtp3_para->nw[nw].routing[spplace].dpc;
						opc= mtp3_para->nw[nw].routing[spplace].opc;
						get_route_from_other_plat(dpc, nw, mtp3_para->lk[link].e1_to_mtp3, link, opc);
					}
			}
		}

	}
}

BYTE get_route_value(u32 dpc, u8 nw, u32 opc)
{
	network	*sp;
	WORD	i;
	mtp3DPCIndex	*sort_rec = &mtp3SortRoutine.nw[nw];
	int		index;
	ull opc_dpc=0;

	if (dpc==0)
		return 0;
	if(opc == mtp3_para->nw[nw].opc14)
		opc =0;
	opc_dpc = opc;
	opc_dpc = (opc_dpc <<32)|dpc;
	sp = &mtp3.nw[nw];

	index = Mtp3BinSearchValue(0,sort_rec->sortedNum-1,nw,opc_dpc);//??
	if ((index >= 0) && (index < MAX_ROUTE))
		i = sort_rec->index[index];
	else
		return 0;

	 return sp->routine[i];
}

int update_route_by_other_plat(u32 dpc,BYTE nw, BYTE routine, WORD chl, u32 opc)
{
	network	*sp;
	int	i;
	mtp3DPCIndex	*sort_rec = &mtp3SortRoutine.nw[nw];
	int		index;
	ls_info	*ls;
	WORD lsno;
	WORD	lsx16;
	BYTE outroute;	
	lsno = mtp3_para->lk[chl].e1_to_linkset;
	ull opc_dpc=0;

	return 0;
	
	if (lsno >= MAX_LS)
		return 0;	
	if (dpc==0)
		return 0;
	ls = &mtp3.ls[lsno];
	lsx16 = lsno << 4;

	sp = &mtp3.nw[nw];
	if(opc == mtp3_para->nw[nw].opc14)
		opc =0;
	opc_dpc = opc;
	opc_dpc = (opc_dpc <<32)|dpc;
	index = Mtp3BinSearchValue(0,sort_rec->sortedNum-1,nw,opc_dpc);//??-
	if ((index >= 0) && (index < MAX_ROUTE))
		i = sort_rec->index[index];
	else
		return 0;

	if(detail_debug_flag)
		mtp3_debug(MTP3DB_EVENT," <%s:%d> link=%d, linkset=%d, dpc=%d, sp->routine .local=%d,peer=%d", 
				__FUNCTION__, __LINE__,
				chl,
				lsno,
				dpc,
				sp->routine[i],
				routine);
	if(0)
	if(sp->routine[i] != routine)
	{
		outroute =  (sp->routine[i] >> 6) & 3;
		if(outroute != 2)
			return 0;
	}
	
	sp->routine[i] = routine;
	
	outroute =  (routine >> 6) & 3;
	if ( outroute == 2 )/* no outbound route */
	{
		//memset(&ls_sls[lsx16],0xff,16);
		for(i=0; i<16; i++)
		{
			if(sls_to_link[lsx16+i] == chl)
				ls_sls[lsx16+i] = MAX_LK_INDEX;
		}
	}
	else if ( (outroute == 0) &&
			  ((routine & 3) == NLS_AVAILABLE)	)/* current route is normal route */
	{
		//memset(&ls_sls[lsx16],chl,16);
		for(i=0; i<16; i++)
		{
			if(sls_to_link[lsx16+i] == chl)
				ls_sls[lsx16+i] = chl;
		}
	}
	else if ( ((routine >> 2) & 3) == ALS_AVAILABLE)
	{
		//memset(&ls_sls[lsx16],chl,16);
		for(i=0; i<16; i++)
		{
			if(sls_to_link[lsx16+i] == chl)
				ls_sls[lsx16+i] = chl;
		}
	}
	return 1;
}

int send_route_to_other_plat(u32 dpc, BYTE nw, BYTE routine, long dest_ip, WORD chl, u32 opc)
{
   	mtp3_iprt.io_msg.msgSrcPort = 4950;
	mtp3_iprt.io_msg.msgDstPort = 4950;
	mtp3_iprt.io_msg.msgDstIP = dest_ip;
	mtp3_iprt.io_msg.msgContent[4] = 0x2f;
	mtp3_iprt.io_msg.msgContent[5] = nw;
	memcpy(&mtp3_iprt.io_msg.msgContent[6], &dpc, 4);
	mtp3_iprt.io_msg.msgContent[10] = routine;
	memcpy(&mtp3_iprt.io_msg.msgContent[11], &opc, 4);
	mtp3_iprt.io_msg.msgContent[1] = chl>>8;
	mtp3_iprt.io_msg.msgContent[0] = chl&0xFF;
	mtp3_iprt.io_msg.msgContent[2] = 0;
	mtp3_iprt.io_msg.msgContent[3] = 12;
	mtp3_iprt.io_msg.msgLength = (mtp3_iprt.io_msg.msgContent[2]<<8) + mtp3_iprt.io_msg.msgContent[3]+4;
	iptrDirectSendMsg(mtp3_iprt.io_msg);
	return 1;

}
	
#endif
/*
 *  Referenced functions.
 */

/*
 *  Forward declarations.
 */

/*
 *  Consistent with link set and link functions of:
 *
 *      Signalling Message Handling (SMH)
 *      Message Routing (HMRT)
 *      Figure 26/Q.704
 *
 *  Note:- the HMRT state machine is a single state state machine which is
 *  best organized as a series of function calls and the interrogation of the
 *  ls->statem.own_sp_restart flag.  These link set and link functions are
 *  essentially subroutine calls made by the route set and route functions
 *  which are part of the MTPI.
 */

void hmrt_tra_msg(WORD linkset)
{
	ls_info			*ls;
	BYTE			nw;
	long			route_mark;
	BYTE			*sd_tmp_buf;
	int				outlink;

	outlink = check_snmmsg_route(linkset);
	if (outlink == -1)
		return;

	ls = &mtp3.ls[linkset];
	nw = mtp3_para->ls_pro[linkset].nw_id;
	sd_tmp_buf = &mtp3_iprt.io_msg.msgContent[0];
	if ( pc_length(nw) == MTP3_24BIT_PC )
	{
		sd_tmp_buf[2] = 0;
		sd_tmp_buf[3] = 9;
		sd_tmp_buf[4] = nw << 6;
		memcpy(&sd_tmp_buf[5],&mtp3_para->ls_pro[linkset].ls_op_pc,3);
		//memcpy(&sd_tmp_buf[7],&mtp3_para->nw[nw].opc24,3);
		if(mtp3_para->ls_pro[linkset].ls_opc==0)
			memcpy(&sd_tmp_buf[8],&mtp3_para->nw[nw].opc24,3);
		else 
			memcpy(&sd_tmp_buf[8],&mtp3_para->ls_pro[linkset].ls_opc,3);
		sd_tmp_buf[11] = 0;
		sd_tmp_buf[12] = SIGNAL_TRA;
	}
	else
	{
		if(mtp3_para->ls_pro[linkset].ls_opc==0)
			route_mark = (mtp3_para->nw[nw].opc14 << 14) + mtp3_para->ls_pro[linkset].ls_op_pc;
		else 
			route_mark = (mtp3_para->ls_pro[linkset].ls_opc << 14) + mtp3_para->ls_pro[linkset].ls_op_pc;
		sd_tmp_buf[2] = 0;
		sd_tmp_buf[3] = 6;
		sd_tmp_buf[4] = nw << 6;
		memcpy(&sd_tmp_buf[5],&route_mark,4);
		sd_tmp_buf[9] = SIGNAL_TRA;
	}
	sd_tmp_buf[1] = outlink>>8;
	sd_tmp_buf[0] = outlink&0xff;
	send_mtp_msg(outlink,sd_tmp_buf);
	mtp3.nw[nw].flow.MtoI[0]++;
}

void sd_STM_msg(WORD chl, BYTE MsgType)
{
	ls_info			*ls;
	BYTE			nw;
	long			route_mark;
	BYTE			H1;
	BYTE			H0;
	BYTE			supplymsg;
	WORD			ls_no;
	int				outlink=-1;
	BYTE			*sd_tmp_buf;

	ls_no = mtp3_para->lk[chl].e1_to_linkset;
	ls = &mtp3.ls[ls_no];
	nw = mtp3_para->ls_pro[ls_no].nw_id;

	sd_tmp_buf = &mtp3_iprt.io_msg.msgContent[0];
	if ( pc_length(nw) == MTP3_24BIT_PC )
	{
		sd_tmp_buf[2] = 0;
		sd_tmp_buf[3] = 9;
		sd_tmp_buf[4] = nw << 6;
		memcpy(&sd_tmp_buf[5],&mtp3_para->ls_pro[ls_no].ls_op_pc,3);
//		memcpy(&sd_tmp_buf[7],&mtp3_para->nw[nw].opc24,3);
		if(mtp3_para->ls_pro[ls_no].ls_opc==0)
			memcpy(&sd_tmp_buf[8],&mtp3_para->nw[nw].opc24,3);
		else 
			memcpy(&sd_tmp_buf[8],&mtp3_para->ls_pro[ls_no].ls_opc,3);
		sd_tmp_buf[11] = mtp3_para->lk[chl].e1_to_slc;
		sd_tmp_buf[12] = MsgType;
		supplymsg = 11+1+1;
	}
	else
	{
		if(mtp3_para->ls_pro[ls_no].ls_opc==0)
			route_mark = (mtp3_para->lk[chl].e1_to_slc << 28) + (mtp3_para->nw[nw].opc14 << 14) + mtp3_para->ls_pro[ls_no].ls_op_pc;
		else
			route_mark = (mtp3_para->lk[chl].e1_to_slc << 28) + (mtp3_para->ls_pro[ls_no].ls_opc << 14) + mtp3_para->ls_pro[ls_no].ls_op_pc;
		sd_tmp_buf[2] = 0;
		sd_tmp_buf[3] = 6;
		sd_tmp_buf[4] = nw << 6;
		memcpy(&sd_tmp_buf[5],&route_mark,4);
		sd_tmp_buf[9] = MsgType;
		supplymsg = 8+1+1;
	}

	H0 = MsgType & 0x0F;
	H1 = MsgType >> 4;

	switch (H0)
	{
		case 1:
			switch (H1)
			{
				case 1:/* COO */
					sd_tmp_buf[3] = sd_tmp_buf[3] + 1;
					sd_tmp_buf[supplymsg] = retrieved_bsnt[chl];
					mtp3_debug(MTP3DB_EVENT,"Link %d SEND COO,SUP MSG=%d",chl,sd_tmp_buf[supplymsg]);
					mtp3_debug(MTP3DB_EVENT,"Link %d SEND COO,BSNT=%d",chl,retrieved_bsnt[chl]);
					outlink = search_outbound_coLink(chl);
					break;
				case 2:/* COA */
					sd_tmp_buf[3] = sd_tmp_buf[3] + 1;
					sd_tmp_buf[supplymsg] = retrieved_bsnt[chl];
					mtp3_debug(MTP3DB_EVENT,"Link %d SEND COA,SUP MSG=%d",chl,sd_tmp_buf[supplymsg]);
					mtp3_debug(MTP3DB_EVENT,"Link %d SEND COA,BSNT=%d",chl,retrieved_bsnt[chl]);
					outlink = search_outbound_coLink(chl);
					break;
				case 5:/* CBD */
					sd_tmp_buf[3] = sd_tmp_buf[3] + 1;
					sd_tmp_buf[supplymsg] = cbc_s[chl];
					outlink = search_outbound_coLink(chl);
					break;
				case 6:/* CBA */
					sd_tmp_buf[3] = sd_tmp_buf[3] + 1;
					sd_tmp_buf[supplymsg] = cbd_cbc_r[chl];
					outlink = search_outbound_coLink(chl);
					break;
				default:
					break;
			}
			break;
		case 2:
			switch (H1)
			{
				case 1:/* ECO */
					outlink = search_outbound_coLink(chl);
					break;
				case 2:/* ECA */
					outlink = search_outbound_coLink(chl);
					break;
				default:
					break;
			}
			break;
		case 6:
			switch (H1)
			{
				case 1:// LIN
					if (mtp3ObjState.link_l3_state[chl] == AVAILABLE)
						outlink = chl;
					else
						outlink = search_outbound_coLink(chl);
					break;
				case 2:// LUN
					if ((link_inhibited[chl] == TRUE) && (mtp3ObjState.link_l2_state[chl] == MTP2_STATE_WORKING))
					{
						outlink=chl;
					}
					else
						outlink = search_outbound_coLink(chl);
/*					if (outlink == -1)
						outlink = chl;*/
					break;
				case 3:// LIA
					if (mtp3ObjState.link_l3_state[chl] == AVAILABLE)
						outlink = chl;
					else
						outlink = search_outbound_coLink(chl);
					break;
				case 4:// LUA
					if ((link_inhibited[chl] == TRUE) && (mtp3ObjState.link_l2_state[chl] == MTP2_STATE_WORKING))
					{
						outlink=chl;
					}
					else if (mtp3ObjState.link_l3_state[chl] == AVAILABLE)
						outlink = chl;
					else
						outlink = search_outbound_coLink(chl);
/*					if (outlink == -1)
						outlink = chl;*/
					break;
				case 5:// LID
					if (mtp3ObjState.link_l3_state[chl] == AVAILABLE)
						outlink = chl;
					else
						outlink = search_outbound_coLink(chl);
					break;
				case 6:// LFU
					if (mtp3ObjState.link_l3_state[chl] == AVAILABLE)
						outlink = chl;
					else if ((link_inhibited[chl] == TRUE) && (mtp3ObjState.link_l2_state[chl] == MTP2_STATE_WORKING))
						outlink=chl;
					else
						outlink = search_outbound_coLink(chl);
/*					if (outlink == -1)
						outlink = chl;*/
					break;
				case 7:// LLT
					if ((link_inhibited[chl] == TRUE) && (mtp3ObjState.link_l2_state[chl] == MTP2_STATE_WORKING))
					{
						outlink=chl;
					}
					else if (mtp3ObjState.link_l3_state[chl] == AVAILABLE)
						outlink = chl;
					else
						outlink = search_outbound_coLink(chl);
					break;
				case 8:// LRT
					if ((link_inhibited[chl] == TRUE) && (mtp3ObjState.link_l2_state[chl] == MTP2_STATE_WORKING))
					{
						outlink=chl;
					}
					else if (mtp3ObjState.link_l3_state[chl] == AVAILABLE)
						outlink = chl;
					else
						outlink = search_outbound_coLink(chl);
					break;
				default:
					break;
			}
			break;
		default:
			break;
	}
	if (outlink != -1)
	{
		sd_tmp_buf[0] = outlink;
		send_mtp_msg(outlink,sd_tmp_buf);
	}
}

void hmrt_xxxx_adjacent_sp_restart(ls_info *ls)
{
    if ( own_sp_restarting )
	{
        ls->adjacentsp_restarting = 1;
        hmrt_xxxx_adjacent_sp_restart(ls);
    }
}

void hmrt_hmdc_message_for_routing(ls_info *ls)
{
//    ls_prim_t *p = (ls_prim_t *)mp->b_rptr;
//    chl = &ls->device[p->sig.mh.rl.sls];
    /*
     *  This function is called only by the MTP state machines (HMCG) to route
     *  a message once the link set has been selected.
     */
//      hmcg_hmrt_message(ls, mp);
}

void hmrt_tfrc_update_routing_tables(WORD dst, BYTE nw)
{
	network		*sp;
	BYTE		routine;

	sp = &mtp3.nw[nw];
	routine = sp->routine[dst];

	if (Nlinkset_status(routine) == LS_AVAILABLE)
//	if ( Nls_state == 0 )
		sp->routine[dst] = sp->routine[dst] & 0x3f;/* current route is normal route */
	else if (Alinkset_status(routine) == LS_AVAILABLE)
//	else if ( Als_state == 0 )
		sp->routine[dst] = ( sp->routine[dst] & 0x3f ) + 0x40;/* current route is Alternative route */
	else
		sp->routine[dst] = ( sp->routine[dst] & 0x3f ) + 0x80;/* no route */
}

void hmrt_sltc_signalling_link_test_msg(WORD chl)
{
	WORD	linkset;
	ls_info	*ls;
	WORD	sp_place;
	BYTE	nw;
	long	route_mark;
	BYTE	*sd_tmp_buf;
	BYTE	slc;

	linkset = mtp3_para->lk[chl].e1_to_linkset;
	if (linkset >= MAX_LS)
	{
		mtp3_debug(MTP3DB_EVENT,"Warning!! link %d doesn't asign a linkset,stop test procedure",chl);
		return;
	}
	nw = mtp3_para->ls_pro[linkset].nw_id;
	ls = &mtp3.ls[linkset];
	sp_place = ls->adjacent_sp_place;
	if (sp_place >= MAX_ROUTE)
	{
		mtp3_debug(MTP3DB_EVENT,"Warning!! linkset %d remote SPC doesn't config in the routine table,stop test procedure",linkset);
		return;
	}
	slc = mtp3_para->lk[chl].e1_to_slc;

	sd_tmp_buf = &mtp3_iprt.io_msg.msgContent[0];
	if (pc_length(nw) == MTP3_24BIT_PC)
	{
		sd_tmp_buf[1] = chl>>8;
		sd_tmp_buf[0] = chl	&0xff;	
		sd_tmp_buf[2] = 0;
		sd_tmp_buf[3] = 12;
		if (mtp3ObjState.lk_SpecANSI_flag[chl] == 1)
			sd_tmp_buf[4] = (nw << 6) + 2;
		else
			sd_tmp_buf[4] = (nw << 6) + 1;
		memcpy(&sd_tmp_buf[5],&mtp3_para->ls_pro[linkset].ls_op_pc,3);
		//memcpy(&sd_tmp_buf[7],&mtp3_para->nw[nw].opc24,3);
		if(mtp3_para->ls_pro[linkset].ls_opc==0)
			memcpy(&sd_tmp_buf[8],&mtp3_para->nw[nw].opc24,3);
		else 
			memcpy(&sd_tmp_buf[8],&mtp3_para->ls_pro[linkset].ls_opc,3);
		sd_tmp_buf[11] = slc;
		sd_tmp_buf[12] = SIGNAL_SLTM;
		if (mtp3ObjState.lk_SpecANSI_flag[chl] == 1)
			sd_tmp_buf[13] = 0x20+slc;
		else
			sd_tmp_buf[13] = 0x20;
		sd_tmp_buf[14] = chl;//???
		sd_tmp_buf[15] = slc;
	}
	else
	{
		if(mtp3_para->ls_pro[linkset].ls_opc==0)
			route_mark = (slc << 28) + (mtp3_para->nw[nw].opc14 << 14) + (mtp3_para->ls_pro[linkset].ls_op_pc);
		else 
			route_mark = (slc << 28) + (mtp3_para->ls_pro[linkset].ls_opc << 14) + (mtp3_para->ls_pro[linkset].ls_op_pc);
		sd_tmp_buf[1] = chl>>8;
		sd_tmp_buf[0] = chl&0xFF;
		sd_tmp_buf[2] = 0;
		sd_tmp_buf[3] = 9;
		if (mtp3ObjState.lk_SpecANSI_flag[chl] == 1)
			sd_tmp_buf[4] = (nw << 6) + 2;
		else
			sd_tmp_buf[4] = (nw << 6) + 1;
		memcpy(&sd_tmp_buf[5],&route_mark,4);
		sd_tmp_buf[9] = SIGNAL_SLTM;
		if (mtp3ObjState.lk_SpecANSI_flag[chl] == 1)
			sd_tmp_buf[10] = 0x20+slc;
		else
			sd_tmp_buf[10] = 0x20;
		sd_tmp_buf[11] = chl;//???
		sd_tmp_buf[12] = slc;
	}

	send_mtp_msg(chl,sd_tmp_buf);
}

void hmrt_tcbc_changeback_ack(WORD chl)
{
	sd_STM_msg(chl,SIGNAL_CBA);
}

void hmrt_tcbc_changeback_declaration(WORD chl)
{

/*	for ( i=0; i<changeback_lk[17]; i++ )
	{
		cbc_s[chl] = changeback_lk[i];
		sd_STM_msg(chl,SIGNAL_CBD);
	}*/
	cbc_s[chl] = chl;
	sd_STM_msg(chl,SIGNAL_CBD);
}


void hmrt_tcoc_changeover_ack(WORD chl)
{
	sd_STM_msg(chl,SIGNAL_COA);
}

void hmrt_tcoc_changeover_order(WORD chl)
{
	sd_STM_msg(chl,SIGNAL_COO);
}

void hmrt_tcoc_emergency_changeover_ack(WORD chl)
{
	sd_STM_msg(chl,SIGNAL_ECA);
}

void hmrt_tcoc_emergency_changeover_order(WORD chl)
{
	sd_STM_msg(chl,SIGNAL_ECO);
}

/* update route table will update 2 tables
 * 1. routine table: current route(routine's 6-7bits)
 * 2. ls_sls table: every sls's route rules within current route
 */

BOOL Nlinkset_status(BYTE routine)
{
	if ( (routine & 3) == 0)
		return LS_AVAILABLE;
	else
		return LS_UNAVAILABLE;
}

BOOL Alinkset_status(BYTE	routine)
{
	if (((routine >> 2) & 3) == 0 )
		return LS_AVAILABLE;
	else
		return LS_UNAVAILABLE;
}

int scan_ls_link_available(WORD ls_no)
{
	int chl,lk_available;

	lk_available = 0;
	for(chl=0; chl < MAX_LK; chl++)
	{
		if(mtp3ObjState.link_l3_state[chl] == AVAILABLE && mtp3_para->lk[chl].e1_to_linkset == ls_no)
			lk_available++;
	}
	return lk_available;
}
void hmrt_tcbc_update_routing_tables(WORD chl)
{
	BYTE	i,j;
	ls_info	*ls;
	network	*sp;
	ulong	nw;
	unsigned int		lsno;
	WORD	lsx16;
	ulong	spplace;
	WORD	link_num;
	unsigned int sls;
	BYTE	*routine;
	BYTE link_already_available;

	lsno = mtp3_para->lk[chl].e1_to_linkset;
	if (lsno >= MAX_LS)
		return;
	ls = &mtp3.ls[lsno];
	lsx16 = lsno << 4;
	nw = mtp3_para->ls_pro[lsno].nw_id;
	link_num = ls->linksNum_configured;
//	link_num = linknum_in_ls[lsno];
	if (link_num == 0)
	{
		mtp3_debug(MTP3DB_EVENT,"linkset %d havn't config active link",lsno);
//		mtp_send_error("Linkset",lsno,"LINKSET HAVN'T CONFIG ACTIVE LINK");
		return;
	}

	link_already_available = mtp3ObjState.link_l3_state[chl];
	ls->links_available_t = scan_ls_link_available(lsno);

	mtp3ObjState.link_l3_state[chl] = AVAILABLE;
	set_heartbeat(ALARM_LINK_AVAILABLE,chl);

	if (mtp3ObjState.lk_mtp3[chl] == mtp3_localip)
		mtp3_send_alarm(MTP3_LINK_COMPONENT+chl,0);//clear alarm

	if ( ls->links_available_t > 0 )/* WITHIN LS */
	{
		for ( j=0; j<16; j++ )
		{
			sls = lsx16+j;
			if ( (ls_sls[sls] != chl)	&&
				 (sls_to_link[sls] == chl)	)
				ls_sls[sls] = chl;
		}
	}
	else
	{
		current_active_ls_num++;
		current_measure->ls_measure[lsno][2]++;/* STOP of link set failure */
		sp = &mtp3.nw[nw];
		//memset(&ls_sls[lsx16],chl,16);
		for(i=0; i<16; i++)
				ls_sls[lsx16+i] = chl;
		for ( i=0; i<(ls->influ_dstnum_asNLS % MAX_LS_DPC_ADD1); i++ )
		{
			spplace = ls->influ_dstplace_intable_asNLS[i];
			routine = (BYTE*)&sp->routine[spplace];
			if(detail_debug_flag)
			mtp3_debug(MTP3DB_EVENT,"\33[32m%s:%d :  Link %d Linkset %d , routine: =%02x\33[0m",__FUNCTION__, __LINE__, chl, lsno,
				*routine);

			mark_normal_linkset_available(routine); //117-11-07

			if (Nlinkset_status(*routine) == LS_AVAILABLE)
			{
				*routine = ((*routine) & 0x3f);/* current route is normal linkset */
				if(1)
				if(ls->links_nls_asp_ac_send_flag[spplace] == 0)
				{
					ls->links_nls_asp_ac_send_flag[spplace] = 1;
					ls->send_asp_ac_link_id = chl;
				}
			}
			else if (Alinkset_status(*routine) == LS_AVAILABLE)
			{
				(*routine) = ((*routine) & 0x3f) + 0x40;
				if(1)
				if(ls->links_als_asp_ac_send_flag[spplace] == 0)
				{
					ls->links_als_asp_ac_send_flag[spplace] = 1;
					ls->send_asp_ac_link_id = chl;
				}
			}
			else
			{
				//mark_normal_linkset_available(routine);

				(*routine) = ((*routine) & 0x3f) + 0x80;
				
				primitive_to_userpart(nw,mtp3_para->nw[nw].routing[spplace].dpc,AVAILABLE);
			}
			if(detail_debug_flag)
			mtp3_debug(MTP3DB_EVENT,"\33[32m%s:%d :  Link %d Linkset %d , routine: =%02x\33[0m",__FUNCTION__, __LINE__, chl, lsno,
				*routine);

		}

		for ( i=0; i<(ls->influ_dstnum_asALS % MAX_LS_DPC_ADD1); i++ )
		{
			spplace = ls->influ_dstplace_intable_asALS[i];
			routine = (BYTE*)&sp->routine[spplace];

			if(detail_debug_flag)
			mtp3_debug(MTP3DB_EVENT,"\33[32m%s:%d :  Link %d Linkset %d , ssplace=%d, routine: =%02x\33[0m",__FUNCTION__, __LINE__, chl, lsno,
				spplace, *routine);

			mark_alternative_linkset_available(routine); //17-11-07

			if ( (*routine) >> 6 == 2 )/* no route */
			{
				(*routine) = ((*routine) & 0x3f) + 0x40;/* current route is alternative linkset */
				primitive_to_userpart(nw,mtp3_para->nw[nw].routing[spplace].dpc,AVAILABLE);
			}

			if (Nlinkset_status(*routine) == LS_AVAILABLE)
				(*routine) = ((*routine) & 0x3f);/* current route is normal linkset */
			else if (Alinkset_status(*routine) == LS_AVAILABLE)
				(*routine) = ((*routine) & 0x3f) + 0x40;
			else
				(*routine) = ((*routine) & 0x3f) + 0x80;

			if(1)
			if(ls->links_als_asp_ac_send_flag[spplace] == 0)
			{
				ls->links_als_asp_ac_send_flag[spplace] = 1;
				ls->send_asp_ac_link_id = chl;
			}

			if(detail_debug_flag)
			mtp3_debug(MTP3DB_EVENT,"\33[32m%s:%d :  Link %d Linkset %d , routine: =%02x\33[0m",__FUNCTION__, __LINE__, chl, lsno,
				*routine);

		}
		//if (mtp3ObjState.lk_mtp3[chl] == mtp3_localip) for dual alarm issue
			mtp3_send_alarm(lsno+MTP3_LINKSET_COMPONENT,0);
		set_heartbeat(ALARM_LS_AVAILABLE,lsno);
		mtp3_para->ls_pro[lsno].ls_state = 1;//ALARM_LS_AVAILABLE;
	}

	ls->links_available_t = scan_ls_link_available(lsno);

	if (mtp3ObjState.lk_mtp3[chl] == mtp3_localip)
		mtp3_send_alarm(MTP3_LINK_COMPONENT+chl,0);
	else
	{
		if(ls->links_available_t >= 1)
		{
			if(ls->send_asp_ac_link_id == 0 || ls->send_asp_ac_link_id == 0xffff)
				ls->send_asp_ac_link_id = chl;			
		}
	}
	
	if ( ls->links_available_t > 0 )
	{
		if(detail_debug_flag)			
			mtp3_debug(MTP3DB_EVENT,"\33[32m%s: Link %d L3 in service,links_available_t=%d\33[0m",__FUNCTION__, chl, ls->links_available_t);
	}
	else
	{
		if(detail_debug_flag)	
			mtp3_debug(MTP3DB_EVENT,"\33[32m%s: Link %d L3 in service,Linkset %d in service\33[0m",__FUNCTION__, chl,lsno);
	}

	/*
	if(link_already_available != AVAILABLE)
		ls->links_available_t++;
	else
		mtp3_debug(MTP3DB_ERROR,"update routing table fail, links=%d have already available", chl);
	*/
	
	current_measure->lk_measure1[chl][1]++;/* local changeback */

//	printf("\r\n     tcbc %d update routine cmp link_available = %d \n\r",chl, ls->links_available_t);
}

void sp_unaccessable(BYTE *routine)
{
	(*routine) = ((*routine) & 0x3f) + 0x80;
}

void hmrt_tcoc_update_routing_tables(WORD chl)
{
	BYTE	i,j;
	ls_info	*ls;
	network	*sp;
	ulong	nw;
	int		lsno;
	int		lsx16;
	BYTE	select_slc;
	WORD	slc[16];
	ulong	spplace;
	int		link;
	BYTE lk_available;

	lsno = mtp3_para->lk[chl].e1_to_linkset;
	ls = &mtp3.ls[lsno];
	lsx16 = lsno << 4;

	ls->links_available_t = scan_ls_link_available(lsno);
	lk_available = mtp3ObjState.link_l3_state[chl];
	nw = mtp3_para->ls_pro[lsno].nw_id;
	if (link_inhibited[chl] == TRUE)
		mtp3ObjState.link_l3_state[chl] = INHIBITED;
	else
	{
		mtp3ObjState.link_l3_state[chl] = UNAVAILABLE;
		mtp3ObjState.link_enable_sent_flag[chl] = 0;

	}
	
	set_heartbeat(ALARM_LINK_UNAVAILABLE,chl);

	if (ls->links_available_t > 0 && lk_available == AVAILABLE)
		ls->links_available_t--;
	else
		mtp3_debug(MTP3DB_ERROR,"hmrt_tcoc_update routing table fail, links=%d have already unavailable", chl);

	if ( ls->links_available_t > 0 )/* within ls */
	{
		j = 0;
		for ( i=0; i<16; i++ )
		{
			link = ls_slc[lsx16+i];
			if ( (link != chl) && (mtp3ObjState.link_l3_state[link] == AVAILABLE) )
			{
				slc[j] = link;
				j++;
			}
		}

		for ( j=0; j<16; j++ )
		{
			if (ls_sls[lsx16+j] == chl)
			{
				if (ls->links_available_t == 0)
				{
					mtp3_debug(MTP3DB_ERROR,"LINKSET %d ERROR,LINKS AVAILABLE = 0\n\r",lsno);
					return;
				}
				select_slc = (j % ls->links_available_t);
				ls_sls[lsx16+j] = slc[select_slc];
			}
		}
/*		if (mtp3_para->lk[chl].e1_to_mtp3 == mtp3_localip)
			mtp3_send_alarm(0,0);*/
	}
	else/* changeover between link set */
	{
		current_measure->ls_measure[lsno][1]++;/* Start of link set failure */
		sp = &mtp3.nw[nw];
		for ( i=0; i<(ls->influ_dstnum_asNLS % MAX_LS_DPC_ADD1); i++ )
		{
			spplace = ls->influ_dstplace_intable_asNLS[i];
			if ( ((sp->routine[spplace] >> 2) & 3) == 0 )/*alternative route available */
				sp->routine[spplace] = (sp->routine[spplace] & 0x3f) + 0x40;/* current route change from normal linkset to alternative linkset */
			else/* sp not accessible */
			{
				sp_unaccessable(&sp->routine[spplace]);
				primitive_to_userpart(nw,mtp3_para->nw[nw].routing[spplace].dpc,UNAVAILABLE);
				sp->m3ua_rc_status[spplace] = 0;
			}
			if(detail_debug_flag)
				mtp3_debug(MTP3DB_ERROR,"%s:%d, Link=%d, changeover DPC=%d, rc_status=%d", __FUNCTION__, __LINE__,
					chl, 	mtp3_para->nw[nw].routing[spplace].dpc, sp->m3ua_rc_status[spplace]);

		}

		for ( i=0; i<(ls->influ_dstnum_asALS % MAX_LS_DPC_ADD1); i++ )
		{
			spplace = ls->influ_dstplace_intable_asALS[i];
			if ( (sp->routine[spplace] & 3) != 0 )/* normal route unavailable  */
			{
				sp_unaccessable(&sp->routine[spplace]);
				primitive_to_userpart(nw,mtp3_para->nw[nw].routing[spplace].dpc,UNAVAILABLE);
				sp->m3ua_rc_status[spplace] = 0;
			}
			if(detail_debug_flag)	
				mtp3_debug(MTP3DB_ERROR,"%s:%d, Link=%d, changeover DPC=%d, rc_status=%d", __FUNCTION__, __LINE__,
					chl, 	mtp3_para->nw[nw].routing[spplace].dpc, sp->m3ua_rc_status[spplace]);

		}

		//memset(&ls_sls[lsx16],MAX_LK,16);
		for(i=0; i<16; i++)
				ls_sls[lsx16+i] = MAX_LK_INDEX;

		set_heartbeat(ALARM_LS_UNAVAILABLE,lsno);
		mtp3_para->ls_pro[lsno].ls_state = 0;//ALARM_LS_UNAVAILABLE;
		if (mtp3ObjState.lk_mtp3[chl] == mtp3_localip)
			mtp3_send_alarm(lsno+MTP3_LINKSET_COMPONENT,1);
	}

	ls->links_available_t = scan_ls_link_available(lsno);

	current_measure->lk_measure1[chl][0]++;/* local changeover */
	if ( ls->links_available_t > 0 )/* within ls */
	{
		mtp3_debug(MTP3DB_EVENT,"\33[31m%s : Link %d L3 out of service, links_available_t=%d, asp_ac_link=%d\33[0m",
				__FUNCTION__, chl, ls->links_available_t, ls->send_asp_ac_link_id);
	      rc_timer = 195+(mtp2_systemid%2)*5;
	}
	else
		mtp3_debug(MTP3DB_EVENT,"\33[31m%s : Link %d L3 out of service,Linkset %d out of service\33[0m",
				__FUNCTION__, chl, lsno);
//	printf("/r/ntcoc %d update routine cmp link_available = %d \n",chl, ls->links_available_t);
}

void send_ip_to_mtp2()/* send message to mtp2, tell mtp2 which is it's host mtp3 */
					  /* this message send every 16 second */
{
	static int mtp2_subsys = 0;
	int		i,j;
	int		basePort;
	BYTE	*msgContent;
	BYTE	e1_to_mtp3;

	basePort = mtp2_subsys*8;
	for (i=0;i<8;i++)
	{
		if ((mtp3ObjState.lk_mtp3[basePort+i] == mtp3_localip) &&
		   (mtp3ObjState.lk_configured[basePort+i] == PARA_CONFIGURED)  && (mtp3_para->lk[basePort+i].e1_lk_type == LKTYPE_NONE_SIGTRAN))
		{
			mtp3_iprt.io_msg.msgLength = 14+1+1;
			mtp3_iprt.io_msg.msgContent[0] = 0;
			mtp3_iprt.io_msg.msgContent[1] = 0;
			mtp3_iprt.io_msg.msgContent[2] = 0;
			mtp3_iprt.io_msg.msgContent[3] = 12;
			mtp3_iprt.io_msg.msgContent[4] = 0xff;
			mtp3_iprt.io_msg.msgContent[5] = 0xee;
			mtp3_iprt.io_msg.msgContent[6] = 0xff;
			msgContent = &mtp3_iprt.io_msg.msgContent[7];
			for (j=0;j<8;j++)
			{

				e1_to_mtp3 = mtp3ObjState.lk_mtp3[basePort+j];
				if ((e1_to_mtp3 != mtp3_localip)	||
					(mtp3ObjState.lk_configured[basePort+j] != PARA_CONFIGURED)		)
					msgContent[j] = 0xee;
				else
					msgContent[j] = ((e1_to_mtp3 >> 16) & 0xff)-32;// 172.18.x+32.1
			}
			mtp3_para->nw_pro = mtp3_para->nw[0].pc_len+mtp3_para->nw[1].pc_len*2+mtp3_para->nw[2].pc_len*4+mtp3_para->nw[0].pc_len*8;
			mtp3_para->nw_pro = mtp3_para->nw_pro + mtp3_para->nw[0].pc_type*16+mtp3_para->nw[1].pc_type*32+mtp3_para->nw[2].pc_type*64+mtp3_para->nw[0].pc_type*128;
			msgContent[8] = mtp3_para->nw_pro;
			mtp3_debug(MTP3DB_PRIMITIVE_MSG,"MTP3 send IP to MTP2 %d",mtp2_subsys);
			mtp3_showbuf(MTP3DB_PRIMITIVE_MSG,&mtp3_iprt.io_msg.msgContent[0],14+2);
			send_to_mtp2(LINK_TO_IP(basePort));
			break;
		}
	}
	mtp2_subsys = (mtp2_subsys+1) & 0x1f;
}

void send_command_to_mtp2(WORD chl, BYTE command)
{
	char charCmd[32];

	mtp3_iprt.io_msg.msgLength = 5+1+1;
	mtp3_iprt.io_msg.msgContent[1] = chl>>8;
	mtp3_iprt.io_msg.msgContent[0] = chl&0xFF;
	mtp3_iprt.io_msg.msgContent[2] = 0;
	mtp3_iprt.io_msg.msgContent[3] = 3;
	mtp3_iprt.io_msg.msgContent[4] = 0xff;
	mtp3_iprt.io_msg.msgContent[5] = ((mtp3ObjState.lk_mtp3[chl] >> 16) & 0xff)-32;// 172.18.x+32.1
	mtp3_iprt.io_msg.msgContent[6] = command;

	switch (command)
	{
		case MTP2_ACTIVE_LINK:
			command3[chl] = MTP2_ACTIVE_LINK;
			sprintf(charCmd,"MTP2_ACTIVE_LINK");
			break;
		case MTP2_DEACTIVE_LINK:
			command3[chl] = MTP2_DEACTIVE_LINK;
			sprintf(charCmd,"MTP2_DEACTIVE_LINK");
			break;
		case MTP2_STOP_L2:
			if (link_inhibited[chl] != TRUE)
			{
				command3[chl] = MTP2_STOP_L2;
			}
			else
				return;
			sprintf(charCmd,"MTP2_STOP_L2");
			break;
		case MTP2_EMERGEN_ALIGNMENT:
			command3[chl] = MTP2_EMERGEN_ALIGNMENT;
			sprintf(charCmd,"MTP2_EMERGEN_ALIGNMENT");
			break;
		case MTP2_RETRIEVE:/* not support */
/*			command3[chl] = MTP2_RETRIEVE;
			iprt.io_msg.msgLength = 5;
			iprt.io_msg.msgContent[1] = 3;
			iprt.io_msg.msgContent[4] = fsnc[chl];
			break;*/
			return;
		case MTP3_M2UA_ENABLE:
			sprintf(charCmd,"ENABLE M2UA LINK");
			break;
		default:
			break;
	}
	if (MTP3_LINK_TYPE(chl) == LKTYPE_NONE_SIGTRAN ||MTP3_LINK_TYPE(chl) == LKTYPE_SIGTRAN)
	{
		mtp3_debug(MTP3DB_PRIMITIVE_MSG,"MTP3 send command %s to link %d",charCmd,chl);
		mtp3_showbuf(MTP3DB_PRIMITIVE_MSG,&mtp3_iprt.io_msg.msgContent[0],5+1+1);
	}
	if (MTP3_LINK_TYPE(chl) == LKTYPE_NONE_SIGTRAN)
		send_to_mtp2(LINK_TO_IP(chl));
#if _INCLUDE_M2UA
	else if (MTP3_LINK_TYPE(chl) == LKTYPE_SIGTRAN)
		put_m2ua_msg((m2ua_up_msg_t *) mtp3_iprt.io_msg.msgContent);
#endif
}

int set_m3ua_detail_debug_flag(int flag)
{
	detail_debug_flag = flag;
	return 1;
}
/*@end@*/
