📄 sl_mux.c
字号:
/***************************************************************************** @(#) sl_mux.c,v openss7-0_9_2_E(0.9.2.19) 2006/05/08 11:01:10 ----------------------------------------------------------------------------- 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/05/08 11:01:10 by brian ----------------------------------------------------------------------------- sl_mux.c,v Revision 0.9.2.19 2006/05/08 11:01:10 brian - new compilers mishandle postincrement of cast pointers Revision 0.9.2.18 2006/04/24 05:01:02 brian - call interface corrections Revision 0.9.2.17 2006/03/07 01:11:56 brian - updated headers *****************************************************************************/#ident "@(#) sl_mux.c,v openss7-0_9_2_E(0.9.2.19) 2006/05/08 11:01:10"char const ident[] = "sl_mux.c,v openss7-0_9_2_E(0.9.2.19) 2006/05/08 11:01:10";#include <sys/os7/compat.h>#include <ss7/lmi.h>#include <ss7/sli.h>#define SL_MUX_DESCRIP "SS7/IP SIGNALLING LINK (SL) STREAMS MULTIPLEXING DRIVER."#define SL_MUX_REVISION "LfS $RCSname$ openss7-0_9_2_E(0.9.2.19) 2006/05/08 11:01:10"#define SL_MUX_COPYRIGHT "Copyright (c) 1997-2006 OpenSS7 Corporation. All Rights Reserved."#define SL_MUX_DEVICE "Part of the OpenSS7 Stack for Linux Fast-STREAMS."#define SL_MUX_CONTACT "Brian Bidulock <bidulock@openss7.org>"#define SL_MUX_LICENSE "GPL"#define SL_MUX_BANNER SL_MUX_DESCRIP "\n" \ SL_MUX_REVISION "\n" \ SL_MUX_COPYRIGHT "\n" \ SL_MUX_DEVICE "\n" \ SL_MUX_CONTACT#define SL_MUX_SPLASH SL_MUX_DESCRIP "\n" \ SL_MUX_REVISION#ifdef LINUXMODULE_AUTHOR(SL_MUX_CONTACT);MODULE_DESCRIPTION(SL_MUX_DESCRIP);MODULE_SUPPORTED_DEVICE(SL_MUX_DEVICE);#ifdef MODULE_LICENSEMODULE_LICENSE(SL_MUX_LICENSE);#endif#if defined MODULE_ALIASMODULE_ALIAS("streams-sl_mux");#endif#endif /* LINUX */#ifdef LFS#define SL_MUX_DRV_ID CONFIG_STREAMS_SL_MUX_MODID#define SL_MUX_DRV_NAME CONFIG_STREAMS_SL_MUX_NAME#define SL_MUX_CMAJORS CONFIG_STREAMS_SL_MUX_NMAJORS#define SL_MUX_CMAJOR_0 CONFIG_STREAMS_SL_MUX_MAJOR#define SL_MUX_UNITS CONFIG_STREAMS_SL_MUX_NMINORS#endif/* * ========================================================================= * * STREAMS Definitions * * ========================================================================= */#define DRV_ID SL_MUX_DRV_ID#define DRV_NAME SL_MUX_DRV_NAME#define CMAJORS SL_MUX_CMAJORS#define CMAJOR_0 SL_MUX_CMAJOR_0#define UNITS SL_MUX_UNITS#ifdef MODULE#define DRV_BANNER SL_MUX_BANNER#else /* MODULE */#define DRV_BANNER SL_MUX_SPLASH#endif /* MODULE */STATIC struct module_info sl_minfo = { .mi_idnum = SL_MUX_DRV_ID, /* id */ .mi_idname = SL_MUX_DRV_NAME, /* name */ .mi_minpsz = 0, /* min packet size accepted */ .mi_maxpsz = INFPSZ, /* max packet size accepted */ .mi_hiwat = 10240L, /* high water mark */ .mi_lowat = 512L, /* low water mark */};STATIC int streamscall sl_open(queue_t *, dev_t *, int, int, cred_t *);STATIC int streamscall sl_close(queue_t *, int, cred_t *);STATIC streamscall int sl_r_prim(queue_t *q, mblk_t *mp);STATIC struct qinit sl_rinit = { .qi_putp = NULL, /* put */ .qi_srvp = ss7_osrv, /* service */ .qi_qopen = sl_open, /* open */ .qi_qclose = sl_close, /* close */ .qi_qadmin = NULL, /* admin */ .qi_minfo = &sl_minfo, /* info */ .qi_mstat = NULL, /* stat */};STATIC streamscall int sl_w_prim(queue_t *q, mblk_t *mp);STATIC struct qinit sl_winit = { .qi_putp = ss7_iput, /* put */ .qi_srvp = NULL, /* service */ .qi_qopen = NULL, /* open */ .qi_qclose = NULL, /* close */ .qi_qadmin = NULL, /* admin */ .qi_minfo = &sl_minfo, /* info */ .qi_mstat = NULL, /* stat */};/* * qinit structures (rd and wr side, lower) */STATIC struct module_info sl_lminfo = { .mi_idnum = 0, /* id */ .mi_idname = SL_MUX_DRV_NAME, /* name */ .mi_minpsz = 0, /* min packet size accepted */ .mi_maxpsz = INFPSZ, /* max packet size accepted */ .mi_hiwat = 10240L, /* high water mark */ .mi_lowat = 512L, /* low water mark */};STATIC streamscall int ls_r_prim(queue_t *q, mblk_t *mp);STATIC struct qinit sl_lrinit = { .qi_putp = ss7_iput, /* put */ .qi_srvp = NULL, /* service */ .qi_qopen = NULL, /* open */ .qi_qclose = NULL, /* close */ .qi_qadmin = NULL, /* admin */ .qi_minfo = &sl_lminfo, /* info */ .qi_mstat = NULL, /* stat */};STATIC streamscall int ls_w_prim(queue_t *q, mblk_t *mp);STATIC struct qinit sl_lwinit = { .qi_putp = NULL, /* put */ .qi_srvp = ss7_osrv, /* service */ .qi_qopen = NULL, /* open */ .qi_qclose = NULL, /* close */ .qi_qadmin = NULL, /* admin */ .qi_minfo = &sl_lminfo, /* info */ .qi_mstat = NULL, /* stat */};MODULE_STATIC struct streamtab sl_muxinfo = { .st_rdinit = &sl_rinit, /* read queue */ .st_wrinit = &sl_winit, /* write queue */ .st_muxrinit = &sl_lrinit, /* mux read queue */ .st_muxwinit = &sl_lwinit, /* mux write queue */};/* * ========================================================================= * * Private structure and allocation * * ========================================================================= */typedef struct sl { STR_DECLARATION (struct sl); toid_t sltm_timer; toid_t recovery_timer; size_t sltm_failures; size_t recovery_attempts; queue_t *qbot;} sl_t;#define SL_PRIV(__q) ((struct sl *)((__q)->q_ptr))typedef struct ls { STR_DECLARATION (struct ls); toid_t sltm_timer; toid_t recovery_timer; size_t sltm_failures; size_t recovery_attempts; queue_t *qtop;} ls_t;#define SL_PRIV(__q) ((struct sl *)((__q)->q_ptr))typedef struct df { spinlock_t lock; SLIST_HEAD (sl, sl); SLIST_HEAD (ls, ls);} df_t;STATIC struct df master;/* * ------------------------------------------------------------------------- * * Caches * * ------------------------------------------------------------------------- */STATIC kmem_cache_t *slm_sl_cachep = NULL;STATIC kmem_cache_t *slm_ls_cachep = NULL;STATIC intslm_term_caches(void){ int err = 0; if (slm_ls_cachep) { if (kmem_cache_destroy(slm_ls_cachep)) { cmn_err(CE_WARN, "%s: did not destroy slm_ls_cachep", __FUNCTION__); err = -EBUSY; } else printd(("%s: destroyed slm_ls_cachep\n", DRV_NAME)); } if (slm_sl_cachep) { if (kmem_cache_destroy(slm_sl_cachep)) { cmn_err(CE_WARN, "%s: did not destroy slm_sl_cachep", __FUNCTION__); err = -EBUSY; } else printd(("%s: destroyed slm_sl_cachep\n", DRV_NAME)); } return (err);}STATIC intslm_init_caches(void){ if (!slm_sl_cachep && !(slm_sl_cachep = kmem_cache_create("slm_sl_cachep", sizeof(struct sl), 0, SLAB_HWCACHE_ALIGN, NULL, NULL))) { cmn_err(CE_PANIC, "%s: did not allocate slm_sl_cachep", DRV_NAME); goto error; } else printd(("%s: initialized slm sl structure cache\n", DRV_NAME)); if (!slm_ls_cachep && !(slm_ls_cachep = kmem_cache_create("slm_ls_cachep", sizeof(struct ls), 0, SLAB_HWCACHE_ALIGN, NULL, NULL))) { cmn_err(CE_PANIC, "%s: did not allocate slm_ls_cachep", DRV_NAME); goto error; } else printd(("%s: initialized slm ls structure cache\n", DRV_NAME)); return (0); error: slm_term_caches(); return (-ENOMEM);}/* * ------------------------------------------------------------------------- * * Allocation and Deallocation * * ------------------------------------------------------------------------- */STATIC struct sl *sl_get(struct sl *sl){ assure(sl); if (sl) atomic_inc(&sl->refcnt); return (sl);}STATIC voidsl_put(struct sl *sl){ if (sl && atomic_dec_and_test(&sl->refcnt)) { kmem_cache_free(slm_sl_cachep, sl); printd(("%s: %s: %p: dallocated sl structure\n", DRV_NAME, __FUNCTION__, sl)); }}STATIC struct sl *slm_alloc_sl(queue_t *q, struct sl **spp, major_t cmajor, minor_t cminor, cred_t *crp){ struct sl *sl; printd(("%s: %s: create sl device = %hu:%hu\n", DRV_NAME, __FUNCTION__, cmajor, cminor)); if ((sl = kmem_cache_alloc(slm_sl_cachep, SLAB_ATOMIC))) { bzero(sl, sizeof(*sl)); sl_get(sl); /* first get */ sl->u.dev.cmajor = cmajor; sl->u.dev.cminor = cminor; sl->cred = *crp; spin_lock_init(&sl->qlock); (sl->iq = RD(q))->q_ptr = sl_get(sl); (sl->oq = WR(q))->q_ptr = sl_get(sl); sl->o_prim = sl_r_prim; sl->i_prim = sl_w_prim; sl->o_wakeup = NULL; sl->i_wakeup = NULL; sl->i_state = LMI_UNATTACHED; sl->i_style = LMI_STYLE2; sl->i_version = 2; spin_lock_init(&sl->lock); /* place in master list */ if ((sl->next = *spp)) sl->next->prev = &sl->next; sl->prev = spp; *spp = sl_get(sl); master.sl.numb++; } else printd(("%s: %s: ERROR: failed to allocate sl structure %hu:%hu\n", DRV_NAME, __FUNCTION__, cmajor, cminor)); return (sl);}STATIC voidslm_free_sl(queue_t *q){ struct sl *sl = (struct sl *) q->q_ptr; psw_t flags; ensure(sl, return); printd(("%s: %s: %p: free sl %hu:%hu\n", DRV_NAME, __FUNCTION__, sl, sl->u.dev.cmajor, sl->u.dev.cminor)); spin_lock_irqsave(&sl->lock, flags); { /* stopping bufcalls */ ss7_unbufcall((str_t *) sl); /* flush buffers */ flushq(sl->oq, FLUSHALL); flushq(sl->iq, FLUSHALL); /* remove from master list */ if ((*sl->prev = sl->next)) sl->next->prev = sl->prev; sl->next = NULL; sl->prev = &sl->next; ensure(atomic_read(&sl->refcnt) > 1, sl_get(sl)); sl_put(sl); assure(master.sl.numb > 0); master.sl.numb--; /* remove from queues */ ensure(atomic_read(&sl->refcnt) > 1, sl_get(sl)); sl_put(xchg(&sl->oq->q_ptr, NULL)); ensure(atomic_read(&sl->refcnt) > 1, sl_get(sl)); sl_put(xchg(&sl->iq->q_ptr, NULL)); /* done, check final count */ if (atomic_read(&sl->refcnt) != 1) { pswerr(("%s: %s: %p: ERROR: sl lingering reference count = %d\n", DRV_NAME, __FUNCTION__, sl, atomic_read(&sl->refcnt))); atomic_set(&sl->refcnt, 1); } } spin_unlock_irqrestore(&sl->lock, flags); sl_put(sl); /* final put */ return;}STATIC struct ls *ls_get(struct ls *ls){ assure(ls); if (ls) atomic_inc(&ls->refcnt); return (ls);}STATIC voidls_put(struct ls *ls){ if (ls && atomic_dec_and_test(&ls->refcnt)) { kmem_cache_free(slm_ls_cachep, ls); printd(("%s: %s: %p: deallocated ls structure", DRV_NAME, __FUNCTION__, ls)); }}STATIC struct ls *slm_alloc_ls(queue_t *q, struct ls **lpp, ulong index, cred_t *crp){ struct ls *ls; printd(("%s: %s: create ls index = %lu\n", DRV_NAME, __FUNCTION__, index)); if ((ls = kmem_cache_alloc(slm_ls_cachep, SLAB_ATOMIC))) { bzero(ls, sizeof(*ls)); ls_get(ls); /* first get */ ls->u.mux.index = index; ls->cred = *crp; spin_lock_init(&ls->qlock); (ls->iq = RD(q))->q_ptr = ls_get(ls); (ls->oq = WR(q))->q_ptr = ls_get(ls); ls->i_prim = ls_r_prim; ls->o_prim = ls_w_prim; ls->i_wakeup = NULL; ls->o_wakeup = NULL; ls->i_state = LMI_UNATTACHED; ls->i_version = LMI_STYLE2; spin_lock_init(&ls->lock); /* place in master list */ if ((ls->next = *lpp)) ls->next->prev = &ls->next; ls->prev = lpp; *lpp = ls_get(ls); master.ls.numb++; } else printd(("%s: %s: ERROR: failed to allocate ls structure %lu\n", DRV_NAME, __FUNCTION__, index)); return (ls);}STATIC voidslm_free_ls(queue_t *q){ struct ls *ls = (struct ls *) q->q_ptr; psw_t flags; ensure(ls, return); printd(("%s: %s: %p: free ls %lu\n", DRV_NAME, __FUNCTION__, ls, ls->u.mux.index)); spin_lock_irqsave(&ls->lock, flags); { /* stopping bufcalls */ ss7_unbufcall((str_t *) ls); /* flush buffers */ flushq(ls->oq, FLUSHALL); flushq(ls->iq, FLUSHALL); /* remove from master list */ if ((*ls->prev = ls->next)) ls->next->prev = ls->prev; ls->next = NULL; ls->prev = &ls->next; ensure(atomic_read(&ls->refcnt) > 1, ls_get(ls)); ls_put(ls); assure(master.ls.numb > 0); master.ls.numb--; /* remove from queues */ ensure(atomic_read(&ls->refcnt) > 1, ls_get(ls)); ls_put(xchg(&ls->oq->q_ptr, NULL)); ensure(atomic_read(&ls->refcnt) > 1, ls_get(ls)); ls_put(xchg(&ls->iq->q_ptr, NULL)); /* done, check final count */ if (atomic_read(&ls->refcnt) != 1) { pswerr(("%s: %s: %p: ERROR: ls lingering reference count = %d\n", DRV_NAME, __FUNCTION__, ls, atomic_read(&ls->refcnt))); atomic_set(&ls->refcnt, 1); } } spin_unlock_irqrestore(&ls->lock, flags); ls_put(ls); /* final put */ return;}/* * ========================================================================= * * Message handling and procedures * * ========================================================================= */STATIC void streamscallrestart_link(caddr_t data){ queue_t *q = (queue_t *) data; struct ls *ls = (struct ls *) q->q_ptr; mblk_t *dp; ls->recovery_timer = 0; if ((dp = allocb(sizeof(long), BPRI_MED))) { sl_start_req_t *p; dp->b_datap->db_type = M_PROTO; p = (typeof(p)) dp->b_wptr; dp->b_wptr += sizeof(*p); p->sl_primitive = SL_START_REQ; ptrace(("Sending SL_START_REQ\n")); ls->recovery_attempts++; qreply(q, dp); return; } ls->recovery_timer = timeout(&restart_link, (caddr_t) q, 12 * HZ);}STATIC void streamscall send_sltm(caddr_t data);STATIC void streamscallfailed_sltm(caddr_t data){ queue_t *q = (queue_t *) data; struct ls *ls = (struct ls *) q->q_ptr; ls->sltm_timer = 0; __printd(("mtp: SLTM Failed\n")); if (++(ls->sltm_failures) >= 2) { mblk_t *dp; if ((dp = allocb(sizeof(long), BPRI_MED))) { sl_stop_req_t *p; dp->b_datap->db_type = M_PROTO; p = (typeof(p)) dp->b_wptr; dp->b_wptr += sizeof(*p); p->sl_primitive = SL_STOP_REQ; ptrace(("Sending SL_STOP_REQ\n")); ls->recovery_timer = timeout(&restart_link, (caddr_t) q, 12 * HZ); qreply(q, dp); } } send_sltm(data);}STATIC void streamscallsend_sltm(caddr_t data){ queue_t *q = (queue_t *) data; struct ls *ls = (struct ls *) q->q_ptr; mblk_t *mp; uint dpc = 0x11d8; uint opc = 0x11ae; uint sls = 0; uint h0 = 1; uint h1 = 1; uint tbyte = ((jiffies >> 8) & 0x0f); uint tlen = jiffies & 0x0f; if ((mp = allocb(7 + tlen, BPRI_MED))) { int i; unsigned char *x; mp->b_datap->db_type = M_DATA; mp->b_rptr += 6; mp->b_wptr += 6; x = mp->b_wptr; *x++ = 0x01; /* sio == 1 */ *x++ = dpc; *x++ = ((dpc >> 8) & 0x3f) | (opc << 6); *x++ = (opc >> 2); *x++ = ((opc >> 10) & 0x0f) | (sls << 4); *x++ = h0 | (h1 << 4);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -