📄 slpmod.c
字号:
/***************************************************************************** @(#) slpmod.c,v openss7-0_9_2_E(0.9.2.2) 2006/12/29 12:18:14 ----------------------------------------------------------------------------- Copyright (c) 2001-2006 OpenSS7 Corporation <http://www.openss7.com/> Copyright (c) 1997-2000 Brian F. G. Bidulock <bidulock@openss7.org> All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ----------------------------------------------------------------------------- U.S. GOVERNMENT RESTRICTED RIGHTS. If you are licensing this Software on behalf of the U.S. Government ("Government"), the following provisions apply to you. If the Software is supplied by the Department of Defense ("DoD"), it is classified as "Commercial Computer Software" under paragraph 252.227-7014 of the DoD Supplement to the Federal Acquisition Regulations ("DFARS") (or any successor regulations) and the Government is acquiring only the license rights granted herein (the license rights customarily provided to non-Government users). If the Software is supplied to any unit or agency of the Government other than DoD, it is classified as "Restricted Computer Software" and the Government's rights in the Software are defined in paragraph 52.227-19 of the Federal Acquisition Regulations ("FAR") (or any successor regulations) or, in the cases of NASA, in paragraph 18.52.227-86 of the NASA Supplement to the FAR (or any successor regulations). ----------------------------------------------------------------------------- Commercial licensing and support of this software is available from OpenSS7 Corporation at a fee. See http://www.openss7.com/ ----------------------------------------------------------------------------- Last Modified 2006/12/29 12:18:14 by brian ----------------------------------------------------------------------------- slpmod.c,v Revision 0.9.2.2 2006/12/29 12:18:14 brian - old rpms hate nested ifs, release updates Revision 0.9.2.1 2006/12/27 16:35:55 brian - added slpmod module and fixups for make check target *****************************************************************************/#ident "@(#) slpmod.c,v openss7-0_9_2_E(0.9.2.2) 2006/12/29 12:18:14"static char const ident[] = "slpmod.c,v openss7-0_9_2_E(0.9.2.2) 2006/12/29 12:18:14";/* * This is SLPMOD, an SL module that is pushed over a pipe end to form an internal * pseudo-signalling link. Service primitives on the SL interface at one end of the pipe are * translated into Service primitives on the SL interface at the other end of the pipe. Although * the primaly purpose of such as link is testing, it also has the abilty to provide internal * signalling links for building virtual SS7 networks within a host. */#define _LFS_SOURCE 1#define _SVR4_SOURCE 1#define _MPS_SOURCE 1#include <sys/os7/compat.h>#include <stdbool.h>#ifndef mi_timer#define mi_timer mi_timer_MAC#endif#ifndef mi_timer_alloc#define mi_timer_alloc mi_timer_alloc_MAC#endif#include <ss7/lmi.h>#include <ss7/lmi_ioctl.h>#include <ss7/sdli.h>#include <ss7/sdli_ioctl.h>#include <ss7/sdti.h>#include <ss7/sdti_ioctl.h>#include <ss7/sli.h>#include <ss7/sli_ioctl.h>#define SLPMOD_DESCRIP "Signalling Link (SL) Pipe Module (SLPMOD) STREAMS MODULE."#define SLPMOD_REVISION "OpenSS7 slpmod.c,v openss7-0_9_2_E(0.9.2.2) 2006/12/29 12:18:14"#define SLPMOD_COPYRIGHT "Copyright (c) 1997-2006 OpenSS7 Corporation. All Rights Reserved."#define SLPMOD_DEVICE "Part of the OpenSS7 Stack for Linux Fast-STREAMS."#define SLPMOD_CONTACT "Brian Bidulock <bidulock@openss7.org>"#define SLPMOD_LICENSE "GPL"#define SLPMOD_BANNER SLPMOD_DESCRIP "\n" \ SLPMOD_REVISION "\n" \ SLPMOD_COPYRIGHT "\n" \ SLPMOD_DEVICE "\n" \ SLPMOD_CONTACT "\n"#define SLPMOD_SPLASH SLPMOD_DESCRIP " - " \ SLPMOD_REVISION "\n"#ifdef LINUXMODULE_AUTHOR(SLPMOD_CONTACT);MODULE_DESCRIPTION(SLPMOD_DESCRIP);MODULE_SUPPORTED_DEVICE(SLPMOD_DEVICE);#ifdef MODULE_LICENSEMODULE_LICENSE(SLPMOD_LICENSE);#endif /* MODULE_LICENSE */#ifdef MODULE_ALIASMODULE_ALIAS("streams-slpmod");#endif /* MODULE_ALIAS */#endif /* LINUX */#ifdef LFS#define SLPMOD_MOD_ID CONFIG_STREAMS_SLPMOD_MODID#define SLPMOD_MOD_NAME CONFIG_STREAMS_SLPMOD_NAME#endif /* LFS */#define MOD_ID SLPMOD_MOD_ID#define MOD_NAME SLPMOD_MOD_NAME#ifdef MODULE#define MOD_BANNER SLPMOD_BANNER#else /* MODULE */#define MOD_BANNER SLPMOD_SPLASH#endif /* MODULE */#define SLLOGST 1#define SLLOGTO 2#define SLLOGRX 3#define SLLOGTX 4#define SLLOGTE 5#define SLLOGDA 6struct st { int l_state; /* local management state */ int i_state; /* interface state */ int i_flags; /* interface flags */};struct lk { struct lk *other; /* other link */ struct st state, oldstate; /* state */ mblk_t *t1; /* alignment timer */ queue_t *oq; /* output queue */};struct sl { int mid; /* module id */ int sid; /* stream id */ lock_t lock; int users; queue_t *waitq; struct lk rd, wr;};#define SL_PRIV(q) ((struct sl *)(q)->q_ptr)#define SL_LOC_PRIV(sl, q) ((q->q_flag & QREADR) ? &sl->rd : &sl->wr)#define SL_REM_PRIV(sl, q) ((q->q_flag & QREADR) ? &sl->wr : &sl->rd)static const char *sl_l_state_name(int state){ switch (state) { case LMI_UNATTACHED: return ("LMI_UNATTACHED"); case LMI_ATTACH_PENDING: return ("LMI_ATTACH_PENDING"); case LMI_UNUSABLE: return ("LMI_UNUSABLE"); case LMI_DISABLED: return ("LMI_DISABLED"); case LMI_ENABLE_PENDING: return ("LMI_ENABLE_PENDING"); case LMI_ENABLED: return ("LMI_ENABLED"); case LMI_DISABLE_PENDING: return ("LMI_DISABLE_PENDING"); case LMI_DETACH_PENDING: return ("LMI_DETACH_PENDING"); default: return ("LMI_????"); }}#define SL_POWER_OFF 0#define SL_OUT_OF_SERVICE 1#define SL_ALIGNMENT 2#define SL_ALIGNED_READY 3#define SL_ALIGNED_NOT_READY 4#define SL_IN_SERVICE 5static const char *sl_i_state_name(int state){ switch (state) { case SL_POWER_OFF: return ("SL_POWER_OFF"); case SL_OUT_OF_SERVICE: return ("SL_OUT_OF_SERVICE"); case SL_ALIGNMENT: return ("SL_ALIGNMENT"); case SL_ALIGNED_READY: return ("SL_ALIGNED_READY"); case SL_ALIGNED_NOT_READY: return ("SL_ALIGNED_NOT_READY"); case SL_IN_SERVICE: return ("SL_IN_SERVICE"); default: return ("SL_????"); }}#define SL_LOC_PROC_OUT 0x1#define SL_REM_PROC_OUT 0x2#define SL_EMERGENCY 0x4#define SL_CONG_DISCARD 0x8#define SL_CONG_ACCEPT 0x10static const char *sl_flags_set(int mask){ switch (mask & (SL_LOC_PROC_OUT | SL_REM_PROC_OUT | SL_EMERGENCY)) { case 0: return (""); case SL_LOC_PROC_OUT: return ("(LOC)"); case SL_REM_PROC_OUT: return ("(REM)"); case SL_EMERGENCY: return ("(EMERG)"); case SL_LOC_PROC_OUT | SL_REM_PROC_OUT: return ("(LOC|REM)"); case SL_LOC_PROC_OUT | SL_EMERGENCY: return ("(LOC|EMERG)"); case SL_LOC_PROC_OUT | SL_REM_PROC_OUT | SL_EMERGENCY: return ("(LOC|REM|EMERG)"); default: return ("(error)"); }}static inline intsl_get_l_state(struct lk *lk){ return (lk->state.l_state);}static inline intsl_set_l_state(struct sl *sl, struct lk *lk, int newstate){ int oldstate = sl_get_l_state(lk); if (oldstate != newstate) strlog(sl->mid, sl->sid, SLLOGST, SL_TRACE, "%s <- %s", sl_l_state_name(newstate), sl_l_state_name(oldstate)); return (lk->state.l_state = newstate);}static inline intsl_get_i_state(struct lk *lk){ return (lk->state.i_state);}static inline intsl_set_i_state(struct sl *sl, struct lk *lk, int newstate){ int oldstate = sl_get_i_state(lk); if (oldstate != newstate) strlog(sl->mid, sl->sid, SLLOGST, SL_TRACE, "%s <- %s", sl_i_state_name(newstate), sl_i_state_name(oldstate)); return (lk->state.i_state = newstate);}static inline intsl_get_flags(struct lk *lk){ return (lk->state.i_flags);}static inline intsl_set_flags(struct sl *sl, struct lk *lk, int mask){ int oldflags = sl_get_flags(lk), newflags = oldflags |= mask; if (oldflags != newflags) strlog(sl->mid, sl->sid, SLLOGST, SL_TRACE, "%s", sl_flags_set((newflags ^ oldflags) & mask)); return (lk->state.i_flags = newflags);}static inline intsl_clr_flags(struct sl *sl, struct lk *lk, int mask){ int oldflags = sl_get_flags(lk), newflags = oldflags &= ~mask; if (oldflags != newflags) strlog(sl->mid, sl->sid, SLLOGST, SL_TRACE, "~%s", sl_flags_set((newflags ^ oldflags) & mask)); return (lk->state.i_flags = newflags);}static inline voidsl_timer_start(struct lk *lk, int timer, unsigned long value){ switch (timer) { case 1: mi_timer(lk->t1, value); break; default: break; }}static voidsl_timer_stop(struct lk *lk, int timer){ switch (timer) { case 1: mi_timer_cancel(lk->t1); break; default: break; }}static inline fastcall boolsl_trylock(queue_t *q){ struct sl *sl = SL_PRIV(q); bool rtn = false; pl_t pl; pl = LOCK(&sl->lock, plbase); if (sl->users == 0) { rtn = true; sl->users = 1; } else if (!sl->waitq) { sl->waitq = q; } else if (sl->waitq != q) { qenable(q); } UNLOCK(&sl->lock, pl); return (rtn);}static inline fastcall voidsl_unlock(queue_t *q){ struct sl *sl = SL_PRIV(q); pl_t pl; pl = LOCK(&sl->lock, plbase); sl->users = 0; if (sl->waitq) qenable(XCHG(&sl->waitq, NULL)); UNLOCK(&sl->lock, pl);}static inline mblk_t *sl_allocb(queue_t *q, size_t size, int priority){ mblk_t *mp; if (unlikely(!(mp = allocb(size, priority)))) mi_bufcall(q, size, priority); return (mp);}static inline intlmi_info_ack(struct sl *sl, struct lk *lk, queue_t *q, mblk_t *msg){ lmi_info_ack_t *p; mblk_t *mp; if (likely(!!(mp = sl_allocb(q, sizeof(*p), BPRI_MED)))) { mp->b_datap->db_type = M_PCPROTO; p = (typeof(p)) mp->b_wptr; p->lmi_primitive = LMI_INFO_ACK; p->lmi_version = 1; p->lmi_state = sl_get_l_state(lk); p->lmi_max_sdu = 4096; p->lmi_min_sdu = 1; p->lmi_header_len = 0; p->lmi_ppa_style = LMI_STYLE1; mp->b_wptr += sizeof(*p); freemsg(msg); strlog(sl->mid, sl->sid, SLLOGTX, SL_TRACE, "<- LMI_INFO_ACK"); putnext(lk->oq, mp); return (0); } return (-ENOBUFS);}static inline intlmi_ok_ack(struct sl *sl, struct lk *lk, queue_t *q, mblk_t *msg, sl_ulong prim){ lmi_ok_ack_t *p; mblk_t *mp; if (likely(!!(mp = sl_allocb(q, sizeof(*p), BPRI_MED)))) { mp->b_datap->db_type = M_PCPROTO; p = (typeof(p)) mp->b_wptr; p->lmi_primitive = LMI_OK_ACK; p->lmi_correct_primitive = prim; switch (sl_get_l_state(lk)) { case LMI_ATTACH_PENDING: p->lmi_state = sl_set_l_state(sl, lk, LMI_DISABLED); break; case LMI_DETACH_PENDING: p->lmi_state = sl_set_l_state(sl, lk, LMI_UNATTACHED); break; default: /* FIXME: log error */ p->lmi_state = sl_get_l_state(lk); break; } mp->b_wptr += sizeof(*p); freemsg(msg); strlog(sl->mid, sl->sid, SLLOGTX, SL_TRACE, "<- LMI_OK_ACK"); putnext(lk->oq, mp); return (0); } return (-ENOBUFS);}static inline intlmi_error_ack(struct sl *sl, struct lk *lk, queue_t *q, mblk_t *msg, sl_ulong prim, sl_long err){ lmi_error_ack_t *p; mblk_t *mp; if (likely(!!(mp = sl_allocb(q, sizeof(*p), BPRI_MED)))) { mp->b_datap->db_type = M_PCPROTO; p = (typeof(p)) mp->b_wptr; p->lmi_primitive = LMI_ERROR_ACK; p->lmi_errno = err < 0 ? -err : 0; p->lmi_reason = err < 0 ? LMI_SYSERR : err; p->lmi_error_primitive = prim; p->lmi_state = sl_get_l_state(lk); if (p->lmi_reason != LMI_OUTSTATE) { switch (sl_get_l_state(lk)) { case LMI_ATTACH_PENDING: p->lmi_state = sl_set_l_state(sl, lk, LMI_UNATTACHED);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -