📄 m2pa.c
字号:
static inline mblk_t *m2pa_send_sin(void) { return m2pa_send_status(M2PA_NORMAL_PROVING);}static inline mblk_t *m2pa_send_sie(void) { return m2pa_send_status(M2PA_EMERGENCY_PROVING);}/* * ========================================================================= * * M2PA-Peer --> M2PA-Provider Primitives (Received Messages) * * ========================================================================= */static inline int m2pa_recv_in_service(queue_t *q, mblk_t *pdu){ mblk_t *mp; m2pa_t *m2 = M2PA_PRIV(q); switch ( m2->state ) { case M2PA_AIP: if ( m2->emergency ) { /* * IMPLEMENTATION NOTE:- Here is one case where we * can speed things up. If the other end thiks that * the link is fine (because it has had a chance to * do a SRTT calculation and measurement) it must be * good for us too. Just move to the in service * state. */ if ( !(mp = sl_in_service_ind()) ) return -EAGAIN; m2->state = M2PA_INS; freemsg(tp); putnext(q, mp); return(0); } /* * Wait for the local alignment procedure to completed * normally. Remember that the peer M2PA is in service. */ m2->remote_in_service = 1; return(0); case M2PA_INS_LOCAL: if ( !(mp = sl_in_service_ind()) ) return -EAGAIN; m2->state = M2PA_INS; freemsg(tp); putnext(q, mp); return(0); default: case M2PA_OOS: case M2PA_IDLE: case M2PA_RETRIEVAL: /* we shouldn't be getting these, ignore */ return(0); } return(0);}static inline int m2pa_recv_sipo(queue_t *q, mblk_t *pdu){ m2pa_t *m2 = M2PA_PRIV(q); if ( !(m2->flags & M2PA_FLAG_REM_PROC_OUT) ) { if ( sl_processor_outage_ind(m2) == -ENOBUFS ) return -EAGAIN; m2->flags |= M2PA_FLAG_REM_PROC_OUT; } return(0);}static inline int m2pa_recv_not_sipo(queue_t *q, mblk_t *pdu){ m2pa_t *m2 = M2PA_PRIV(q); if ( m2->flags & M2PA_FLAG_REM_PROC_OUT ) { if ( sl_processor_recovered_ind(m2) == -ENOBUFS ) return -EAGAIN; m2->flags &= ~M2PA_FLAG_REM_PROC_OUT; } return(0);}static inline int m2pa_recv_sib(queue_t *q, mblk_t *pdu){ m2pa_t *m2 = M2PA_PRIV(q); if ( !(m2->flags & M2PA_FLAG_REM_CONG) ) { if ( sl_XXXX_ind(m2) == -ENOBUFS ) return -EAGAIN; m2->flags |= M2PA_FLAG_REM_CONG; m2->t6_timer = timeout(m2->t6_timeout, (long)m2, m2->t6_value); } return(0);}static inline int m2pa_recv_not_sib(queue_t *q, mblk_t *pdu){ m2pa_t *m2 = M2PA_PRIV(q); if ( m2->flags & M2PA_FLAG_REM_CONG ) { if ( sl_XXXX_ind(m2) == -ENOBUFS ) return -EAGAIN; m2->flags &= ~M2PA_FLAG_REM_CONG; untimeout(m2->t6_timer); m2->t6_timer = 0; } return(0);}static inline int m2pa_recv_sios(queue_t *q, mblk_t *pdu){ mblk_t *mp; m2pa_t *m2 = M2PA_PRIV(q); switch ( m2->state ) { case M2PA_ALIGNED: case M2PA_PROVING: if ( !(mp = sl_out_of_service_ind(SL_FAIL_ALIGNMENT_NOT_POSSIBLE)) ) return -EAGAIN; untimeout(m2->t4_timer); m2->t4_timer = 0; m2->t4_timer = 0; /* * Stop AERM functions. */ untimeout(m2->t3_timer); m2->t3_timer = 0; m2->t3_timer = 0; m2->flags &= ~M2PA_EMERGENCY; m2->state = M2PA_OUT_OF_SERVICE; putnext(q, mp); break; } freemsg(pdu); return(0);}static inline int m2pa_recv_sio(queue_t *q, mblk_t *pdu){ mblk_t *mp; m2pa_t *m2 = M2PA_PRIV(q); switch ( m2->state ) { case M2PA_NOT_ALIGNED: if ( m2->flags & M2PA_LOC_EMERGENCY ) { if ( !(mp = m2pa_send_sie()) ) return -EAGAIN; } else { if ( !(mp = m2pa_send_sin()) ) return -EAGAIN; } untimeout(m2->t2_timer); m2->t2_timer = 0; m2->t3_timer = timeout(m2->t3_timeout, (long)m2, m2->t3_value); m2->state = M2PA_ALIGNED; freemsg(pdu); qreply(q, mp); return(0); case M2PA_PROVING: untimeout(m2->t4_timer); m2->t4_timer = 0; /* * FIXME: stop AERM function */ break; m2->t3_timer = timeout(m2->t3_timeout, (long)m2, m2->t3_value); m2->state = M2PA_ALIGNED; freemsg(pdu); return(0); }}static inline int m2pa_recv_sin(queue_t *q, mblk_t *pdu){ mblk_t *mp; m2pa_t *m2 = M2PA_PRIV(q); switch ( m2->state ) { case M2PA_NOT_ALIGNED: untimeout(m2->t2_timer); m2->t2_timer = 0; m2->t2_timer = 0; if ( m2->flags & M2PA_LOC_EMERGENCY ) { if ( !(mp = m2pa_send_sie()) ) return -EAGAIN; } else { if ( !(mp = m2pa_send_sin()) ) return -EAGAIN; } m2->t3_timer = timeout(m2->t3_timeout, (long)m2, m2->t3_value); m2->state = M2PA_ALIGNED; qreply(q, mp); break; case M2PA_ALIGNED: untimeout(m2->t3_timer); m2->t3_timer = 0; /* * Start AERM functions */ m2->t4_timer = timeout(m2->t4_timeout, (long)m2, m2->aerm_opts.t4_value); m2->statem.Cp = 0; m2->statem.further_proving = 0; m2->state = M2PA_PROVING; } freemsg(pdu); return(0);}static inline int m2pa_recv_sie(queue_t *q, mblk_t *pdu){ mblk_t *mp; m2pa_t *m2 = M2PA_PRIV(q); switch ( m2->state ) { case M2PA_NOT_ALIGNED: if ( m2->flags & M2PA_LOC_EMERGENCY ) { if ( !(mp = m2pa_send_sie()) ) return = -EAGAIN; } else { if ( !(mp = m2pa_send_sin()) ) return = -EAGAIN; } m2->flags |= M2PA_REM_EMERGENCY; m2->aerm_opts = m2->aerm_emer_opts; untimeout(m2->t2_timer); m2->t2_timer = 0; m2->t3_timer = timeout(m2->t3_timeout, (long)m2, m2->t3_value); m2->state = M2PA_ALIGNED; qreply(q, mp); break; case M2PA_ALIGNED: m2->flags |= M2PA_REM_EMERGENCY; m2->aerm_opts = m2->aerm_emer_opts; untimeout(m2->t3_timer); m2->t3_timer = 0; /* * Start AERM functions */ m2->t4_timer = timeout(m2->t4_timeout, (long)m2, m2->aerm_opts.t4_value); m2->statem.Cp = 0; m2->statem.further_proving = 0; m2->state = M2PA_PROVING; break; case M2PA_PROVING: if ( m2->flags & M2PA_EMERGENCY ) break; m2->flags |= M2PA_REM_EMERGENCY; m2->aerm_opts = m2->aerm_emer_opts; untimeout(m2->t4_timer); m2->t4_timer = 0; /* * Restart AERM functions with new values */ m2->statem.further_proving = 0; m2->t4_timer = timeout(m2->t4_timeout, (long)m2, m2->aerm_opts.t4_value); break; } freemsg(pdu); return(0);}static inline int m2pa_recv_status(queue_t *q, mblk_t *mp){ int err; uint32_t *s = mp->b_rptr; static int (*jump[])(queue_t *, mblk_t *) = { &m2pa_recv_out_of_service, &m2pa_recv_in_service, &m2pa_recv_processor_outage, &m2pa_recv_processor_ended, &m2pa_recv_, &m2pa_recv_, &m2pa_recv_, &m2pa_recv_, &m2pa_recv_, &m2pa_recv_, }; switch ( *s ) { case M2PA_STATUS_IN_SERVICE: return m2pa_recv_in_service(q, mp); case M2PA_STATUS_PROCESSOR_OUTAGE: return m2pa_recv_sipo(q, mp); case M2PA_STATUS_PROCESSOR_ENDED: return m2pa_recv_not_sipo(q, mp); case M2PA_STATUS_BUSY: return m2pa_recv_sib(q, mp); case M2PA_STATUS_BUSY_ENDED: return m2pa_recv_not_sib(q, mp); case M2PA_STATUS_OUT_OF_SERVICE: return m2pa_recv_sios(q, mp); case M2PA_STATUS_ALIGN: return m2pa_recv_sio(q, mp); case M2PA_STATUS_NORMAL_PROVING: return m2pa_recv_sin(q, mp); case M2PA_STATUS_EMERGENCY_PROVING: return m2pa_recv_sie(q, mp); } return -EPROTO;}static inline int m2pa_recv_data(m2pa_t *m2, mblk_t *dp, uint16_t sid){ switch ( sid ) { case M2PA_STATUS_STREAM: return m2pa_recv_status(m2, dp); default: /* * IMPLEMENTATION NOTE:- Now here's a concept: why * not have multiple links over one M2PA SCTP * association? Gee they are either all busy or all * processor outage or all in service so the one * status channel should be sufficient. Multiple * links in a link-set are just for traffic capacity * and sizing anyways. */ case M2PA_DATA_STREAM: putnext(m2->rq, mp); return(0); } return -EPROTO;}/* * ========================================================================= * * M2PA-User --> M2PA-Provider Primitives (M_CTL, M_PROTO, M_PCPROTO) * * ========================================================================= *//* * ------------------------------------------------------------------------- * * SL-User --> M2PA-Provider MANAGEMENT Primitives * * ------------------------------------------------------------------------- */static int lmi_info_req (queue_t *, mblk_t *);static int lmi_attach_req (queue_t *, mblk_t *);static int lmi_detach_req (queue_t *, mblk_t *);static int lmi_enable_req (queue_t *, mblk_t *);static int lmi_disable_req (queue_t *, mblk_t *);static int lmi_optmgmt_req (queue_t *, mblk_t *);static int (*lmi_m_proto_ops[])(queue_t *, mblk_t *) ={ &lmi_info_req, &lmi_attach_req, &lmi_detach_req, &lmi_enable_req, &lmi_disable_req, &lmi_optmgmt_req};/* * LMI_INFO_REQ: * ------------------------------------------------------------------------- * We have to get some info from the T-Provider before we respond to this, * so pass the information request on. */static int lmi_info_req(queue_t *q, mblk_t *mp){ mblk_t *resp; m2pa_t *m2 = M2PA_PRIV(q); lmi_info_req_t *p = (lmi_info_req_t *)mp->b_rptr; if ( !(resp = t_addr_req()) ) return -EAGAIN; freemsg(mp); putnext(q, resp); return(0);}/* * LMI_ATTACH_REQ: * ------------------------------------------------------------------------- * Note that the PPA is only a local thing. This is the local bind address * for the SCTP association. If we are not a client, we listen on the * connection. It takes an LMI_ENABLE command (from a signalling data link * connection order or from management at setup) to provide the address for * connection. */static int lmi_attach_req(queue_t *q, mblk_t *mp){ mblk_t *resp; m2pa_t *m2 = M2PA_PRIV(q); lmi_attach_req_t *p = (lmi_attach_req_t *)mp->b_rptr; const caddr_t add_ptr = p->lmi_ppa; const size_t add_len = mp->b_wptr - add_ptr; const size_t cons = m2->flags & M2PA_CLIENT ? 0 : 1; if ( m2->m_state != LMI_UNATTACHED || m2->t_state != TS_UNBND ) { if ( !(resp = lmi_error_ack(LMI_OUTSTATE, 0, m2->m_state)) ) return -EAGAIN; freemsg(mp); qreply(q, resp); return(0); } add_ptr = p->lmi_ppa; add_len = mp->b_wptr - add_ptr; if ( !(resp = t_bind_req(add_ptr, add_len, cons)) ) return -EAGAIN; m2->t_state = TS_WACK_BREQ; m2->m_state = LMI_ATTACH_PENDING; freemsg(mp); putnext(q, resp); return(0);}/* * LMI_DETACH_REQ: * ------------------------------------------------------------------------- */static int lmi_detach_req(queue_t *q, mblk_t *mp){ mblk_t *resp; m2pa_t *m2 = M2PA_PRIV(q); lmi_detach_req_t *p = (lmi_detach_req_t *)mp->b_rptr; if ( m2->m_state != LMI_UNATTACHED || m2->t_state != TS_IDLE ) { if ( !(resp = lmi_error_ack(LMI_OUTSTATE, 0, m2->m_state)) ) return -EAGAIN; freemsg(mp); qreply(q, resp); return(0); } if ( !(resp = t_unbind_req()) ) return -EAGAIN; m2->t_state = TS_WACK_UREQ; freemsg(mp); putnext(q, resp); return(0);}/* * LMI_ENABLE_REQ: * ------------------------------------------------------------------------- */static int lmi_enable_req(queue_t *q, mblk_t *mp){ mblk_t *resp; m2pa_t *m2 = M2PA_PRIV(q); lmi_enable_req_t *p = (lmi_enable_req_t *)mp->b_rptr; const caddr_t add_ptr = (caddr_t)(p+1); const size_t add_len = mp->b_wptr - add_ptr; if ( m2->m_state != LMI_DISABLED || m2->t_state != TS_IDLE ) { if ( !(resp = lmi_error_ack(LMI_OUTSTATE, 0, m2->m_state)) ) return -EAGAIN; freemsg(mp); qreply(q, resp); return(0); } if ( !(resp = t_conn_req(add_ptr, add_len)) ) return -EAGAIN; m2->t_state = TS_WACK_CREQ; m2->m_state = LMI_ENABLE_PENDING; freemsg(mp); putnext(q, resp); return(0);}/* * LMI_DISABLE_REQ: * ------------------------------------------------------------------------- */static int lmi_disable_req(queue_t *q, mblk_t *mp){ mblk_t *resp; m2pa_t *m2 = M2PA_PRIV(q); lmi_disable_req_t *p = (lmi_disable_req_t *)mp->b_rptr; if ( m2->m_state != LMI_ENABLED ) { if ( !(resp = lmi_error_ack(LMI_OUTSTATE, 0, m2->m_state)) ) return -EAGAIN; freemsg(mp); qreply(q, resp); return(0); } switch ( m2->t_state ) { case TS_IDLE: if ( !(resp = lmi_ok_ack(LMI_DISABLE_REQ, LMI_DISABLED)) ) return -EAGAIN; m2->m_state = LMI_DISABLED; freemsg(mp); qreply(q, resp); return(0); case TS_DATA_XFER: if ( !(resp = t_discon_req()) ) return -EAGAIN; m2->t_state = TS_WACK_DREQ9; m2->m_state = LMI_DISABLE_PENDING; freemsg(mp); putnext(q, resp); return(0); /* FIXME: more state here to check */ default: if ( !(resp = lmi_error_ack(LMI_SYSERR, EFAULT, m2->m_state)) ) return -EAGAIN; freemsg(mp); qreply(q, resp); return(0); } if ( !(resp = lmi_error_ack(LMI_OUTSTATE, 0, m2->m_state)) ) return -EAGAIN; freemsg(mp); qreply(q, resp); return(0);}/* * LMI_OPTMGMT_REQ: * ------------------------------------------------------------------------- */static int lmi_optmgmt_req(m2pa_t *m2, mblk_t *mp){ mblk_t *resp; m2pa_t *m2 = M2PA_PRIV(q);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -