diff options
author | amurai <amurai@FreeBSD.org> | 1995-01-31 06:29:58 +0000 |
---|---|---|
committer | amurai <amurai@FreeBSD.org> | 1995-01-31 06:29:58 +0000 |
commit | 21ef2761fd1e5a4beb483da8bddf767d36540dce (patch) | |
tree | 3aecd1251d1647032ad1455f304eaeeaab4987d0 /usr.sbin/ppp/lqr.c | |
parent | 0487956fcf018d602bfe99b0e3398c6f4d55680a (diff) | |
download | FreeBSD-src-21ef2761fd1e5a4beb483da8bddf767d36540dce.zip FreeBSD-src-21ef2761fd1e5a4beb483da8bddf767d36540dce.tar.gz |
Diffstat (limited to 'usr.sbin/ppp/lqr.c')
-rw-r--r-- | usr.sbin/ppp/lqr.c | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/usr.sbin/ppp/lqr.c b/usr.sbin/ppp/lqr.c new file mode 100644 index 0000000..c36fb21 --- /dev/null +++ b/usr.sbin/ppp/lqr.c @@ -0,0 +1,259 @@ +/* + * PPP Line Quality Monitoring (LQM) Module + * + * Written by Toshiharu OHNO (tony-o@iij.ad.jp) + * + * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the Internet Initiative Japan, Inc. The name of the + * IIJ may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * o LQR based on RFC1333 + * + * $Id:$ + * + * TODO: + * o LQM policy + * o Allow user to configure LQM method and interval. + */ +#include "fsm.h" +#include "lcpproto.h" +#include "lqr.h" +#include "hdlc.h" +#include "lcp.h" +#include "vars.h" + +struct pppTimer LqrTimer; + +static u_long lastpeerin = (u_long)-1; + +static int lqmmethod; +static int echoseq; +static int gotseq; +static int lqrsendcnt; + +struct echolqr { + u_long magic; + u_long signature; + u_long sequence; +}; + +#define SIGNATURE 0x594e4f54 + +static void +SendEchoReq() +{ + struct fsm *fp = &LcpFsm; + struct echolqr *lqr, lqrdata; + + if (fp->state == ST_OPENED) { + lqr = &lqrdata; + lqr->magic = htonl(LcpInfo.want_magic); + lqr->signature = htonl(SIGNATURE); + LogPrintf(LOG_LQM, "Send echo LQR [%d]\n", echoseq); + lqr->sequence = htonl(echoseq++); + FsmOutput(fp, CODE_ECHOREQ, fp->reqid++, + (u_char *)lqr, sizeof(struct echolqr)); + } +} + +void +RecvEchoLqr(bp) +struct mbuf *bp; +{ + struct echolqr *lqr; + u_long seq; + + if (plength(bp) == sizeof(struct echolqr)) { + lqr = (struct echolqr *)MBUF_CTOP(bp); + if (htonl(lqr->signature) == SIGNATURE) { + seq = ntohl(lqr->sequence); + LogPrintf(LOG_LQM, "Got echo LQR [%d]\n", ntohl(lqr->sequence)); + gotseq = seq; + } + } +} + +void +LqrChangeOrder(src, dst) +struct lqrdata *src, *dst; +{ + u_long *sp, *dp; + int n; + + sp = (u_long *)src; dp = (u_long *)dst; + for (n = 0; n < sizeof(struct lqrdata)/sizeof(u_long); n++) + *dp++ = ntohl(*sp++); +} + +static void +SendLqrReport() +{ + struct mbuf *bp; + + StopTimer(&LqrTimer); + + if (lqmmethod & LQM_LQR) { + if (lqrsendcnt > 5) { + /* + * XXX: Should implement LQM strategy + */ + LogPrintf(LOG_PHASE, "** Too many ECHO packets are lost. **\n"); + LcpClose(); + Cleanup(EX_ERRDEAD); + } else { + bp = mballoc(sizeof(struct lqrdata), MB_LQR); + HdlcOutput(PRI_URGENT, PROTO_LQR, bp); + lqrsendcnt++; + } + } else if (lqmmethod & LQM_ECHO) { + if (echoseq - gotseq > 5) { + LogPrintf(LOG_PHASE, "** Too many ECHO packets are lost. **\n"); + LcpClose(); + Cleanup(EX_ERRDEAD); + } else + SendEchoReq(); + } + + if (lqmmethod && Enabled(ConfLqr)) + StartTimer(&LqrTimer); +} + +void +LqrInput(struct mbuf *bp) +{ + int len; + u_char *cp; + struct lqrdata *lqr; + + len = plength(bp); + if (len != sizeof(struct lqrdata)) { + pfree(bp); + return; + } + + if (!Acceptable(ConfLqr)) { + bp->offset -= 2; + bp->cnt += 2; + + cp = MBUF_CTOP(bp); + LcpSendProtoRej(cp, bp->cnt); + } else { + cp = MBUF_CTOP(bp); + lqr = (struct lqrdata *)cp; + if (ntohl(lqr->MagicNumber) != LcpInfo.his_magic) { +#ifdef notdef +logprintf("*** magic %x != expecting %x\n", ntohl(lqr->MagicNumber), LcpInfo.his_magic); +#endif + pfree(bp); + return; + } + + /* + * Convert byte order and save into our strage + */ + LqrChangeOrder(lqr, &HisLqrData); + LqrDump("LqrInput", &HisLqrData); + lqrsendcnt = 0; /* we have received LQR from peer */ + + /* + * Generate LQR responce to peer, if + * i) We are not running LQR timer. + * ii) Two successive LQR's PeerInLQRs are same. + */ + if (LqrTimer.load == 0 || lastpeerin == HisLqrData.PeerInLQRs) { + lqmmethod |= LQM_LQR; + SendLqrReport(); + } + lastpeerin = HisLqrData.PeerInLQRs; + } + pfree(bp); +} + +/* + * When LCP is reached to opened state, We'll start LQM activity. + */ +void +StartLqm() +{ + struct lcpstate *lcp = &LcpInfo; + int period; + + lqmmethod = LQM_ECHO; + if (Enabled(ConfLqr)) + lqmmethod |= LQM_LQR; + StopTimer(&LqrTimer); + LogPrintf(LOG_LQM, "LQM method = %d\n", lqmmethod); + + if (lcp->his_lqrperiod || lcp->want_lqrperiod) { + /* + * We need to run timer. Let's figure out period. + */ + period = lcp->his_lqrperiod ? lcp->his_lqrperiod : lcp->want_lqrperiod; + StopTimer(&LqrTimer); + LqrTimer.state = TIMER_STOPPED; + LqrTimer.load = period * SECTICKS / 100; + LqrTimer.func = SendLqrReport; + SendLqrReport(); + StartTimer(&LqrTimer); + LogPrintf(LOG_LQM, "Will send LQR every %d.%d secs\n", + period/100, period % 100); + } else { + LogPrintf(LOG_LQM, "LQR is not activated.\n"); + } +} + +void +StopLqr(method) +int method; +{ + LogPrintf(LOG_LQM, "StopLqr method = %x\n", method); + + if (method == LQM_LQR) + LogPrintf(LOG_LQM, "Stop sending LQR, Use LCP ECHO instead.\n"); + if (method == LQM_ECHO) + LogPrintf(LOG_LQM, "Stop sending LCP ECHO.\n"); + lqmmethod &= ~method; + if (lqmmethod) + SendLqrReport(); + else + StopTimer(&LqrTimer); +} + +void +LqrDump(message, lqr) +char *message; +struct lqrdata *lqr; +{ + if (loglevel >= LOG_LQM) { + LogTimeStamp(); + logprintf("%s:\n", message); + LogTimeStamp(); + logprintf(" Magic: %08x LastOutLQRs: %08x\n", + lqr->MagicNumber, lqr->LastOutLQRs); + LogTimeStamp(); + logprintf(" LastOutPackets: %08x LastOutOctets: %08x\n", + lqr->LastOutPackets, lqr->LastOutOctets); + LogTimeStamp(); + logprintf(" PeerInLQRs: %08x PeerInPackets: %08x\n", + lqr->PeerInLQRs, lqr->PeerInPackets); + LogTimeStamp(); + logprintf(" PeerInDiscards: %08x PeerInErrors: %08x\n", + lqr->PeerInDiscards, lqr->PeerInErrors); + LogTimeStamp(); + logprintf(" PeerInOctets: %08x PeerOutLQRs: %08x\n", + lqr->PeerInOctets, lqr->PeerOutLQRs); + LogTimeStamp(); + logprintf(" PeerOutPackets: %08x PeerOutOctets: %08x\n", + lqr->PeerOutPackets, lqr->PeerOutOctets); + } +} |