static void SendLqrReport(void *v) { struct lcp *lcp = (struct lcp *)v; struct physical *p = link2physical(lcp->fsm.link); timer_Stop(&p->hdlc.lqm.timer); if (p->hdlc.lqm.method & LQM_LQR) { if (p->hdlc.lqm.lqr.resent > 5) { /* XXX: Should implement LQM strategy */ log_Printf(LogPHASE, "%s: ** Too many LQR packets lost **\n", lcp->fsm.link->name); log_Printf(LogLQM, "%s: Too many LQR packets lost\n", lcp->fsm.link->name); p->hdlc.lqm.method = 0; datalink_Down(p->dl, CLOSE_NORMAL); } else { SendLqrData(lcp); p->hdlc.lqm.lqr.resent++; } } else if (p->hdlc.lqm.method & LQM_ECHO) { if ((p->hdlc.lqm.echo.seq_sent > 5 && p->hdlc.lqm.echo.seq_sent - 5 > p->hdlc.lqm.echo.seq_recv) || (p->hdlc.lqm.echo.seq_sent <= 5 && p->hdlc.lqm.echo.seq_sent > p->hdlc.lqm.echo.seq_recv + 5)) { log_Printf(LogPHASE, "%s: ** Too many LCP ECHO packets lost **\n", lcp->fsm.link->name); log_Printf(LogLQM, "%s: Too many LCP ECHO packets lost\n", lcp->fsm.link->name); p->hdlc.lqm.method = 0; datalink_Down(p->dl, CLOSE_NORMAL); } else SendEchoReq(lcp); } if (p->hdlc.lqm.method && p->hdlc.lqm.timer.load) timer_Start(&p->hdlc.lqm.timer); }
struct mbuf * lqr_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) { struct physical *p = link2physical(l); struct lcp *lcp = p->hdlc.lqm.owner; int len; if (p == NULL) { log_Printf(LogERROR, "lqr_Input: Not a physical link - dropped\n"); m_freem(bp); return NULL; } len = m_length(bp); if (len != sizeof(struct lqrdata)) log_Printf(LogWARN, "lqr_Input: Got packet size %d, expecting %ld !\n", len, (long)sizeof(struct lqrdata)); else if (!IsAccepted(l->lcp.cfg.lqr) && !(p->hdlc.lqm.method & LQM_LQR)) { bp = m_pullup(proto_Prepend(bp, PROTO_LQR, 0, 0)); lcp_SendProtoRej(lcp, MBUF_CTOP(bp), bp->m_len); } else { struct lqrdata *lqr; bp = m_pullup(bp); lqr = (struct lqrdata *)MBUF_CTOP(bp); if (ntohl(lqr->MagicNumber) != lcp->his_magic) log_Printf(LogWARN, "lqr_Input: magic 0x%08lx is wrong," " expecting 0x%08lx\n", (u_long)ntohl(lqr->MagicNumber), (u_long)lcp->his_magic); else { struct lqrdata lastlqr; memcpy(&lastlqr, &p->hdlc.lqm.lqr.peer, sizeof lastlqr); lqr_ChangeOrder(lqr, &p->hdlc.lqm.lqr.peer); lqr_Dump(l->name, "Input", &p->hdlc.lqm.lqr.peer); /* we have received an LQR from our peer */ p->hdlc.lqm.lqr.resent = 0; /* Snapshot our state when the LQR packet was received */ memcpy(&p->hdlc.lqm.lqr.prevSave, &p->hdlc.lqm.lqr.Save, sizeof p->hdlc.lqm.lqr.prevSave); p->hdlc.lqm.lqr.Save.InLQRs = ++p->hdlc.lqm.lqr.InLQRs; p->hdlc.lqm.lqr.Save.InPackets = p->hdlc.lqm.ifInUniPackets; p->hdlc.lqm.lqr.Save.InDiscards = p->hdlc.lqm.ifInDiscards; p->hdlc.lqm.lqr.Save.InErrors = p->hdlc.lqm.ifInErrors; p->hdlc.lqm.lqr.Save.InOctets = p->hdlc.lqm.lqr.InGoodOctets; lqr_Analyse(&p->hdlc, &lastlqr, &p->hdlc.lqm.lqr.peer); /* * Generate an LQR response if we're not running an LQR timer OR * two successive LQR's PeerInLQRs are the same. */ if (p->hdlc.lqm.timer.load == 0 || !(p->hdlc.lqm.method & LQM_LQR) || (lastlqr.PeerInLQRs && lastlqr.PeerInLQRs == p->hdlc.lqm.lqr.peer.PeerInLQRs)) SendLqrData(lcp); } } m_freem(bp); return NULL; }