Deleted Added
sdiff udiff text old ( 28679 ) new ( 28974 )
full compact
1/*
2 * PPP Line Quality Monitoring (LQM) Module
3 *
4 * Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5 *
6 * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7 *
8 * Redistribution and use in source and binary forms are permitted
9 * provided that the above copyright notice and this paragraph are
10 * duplicated in all such forms and that any documentation,
11 * advertising materials, and other materials related to such
12 * distribution and use acknowledge that the software was developed
13 * by the Internet Initiative Japan, Inc. The name of the
14 * IIJ may not be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 *
20 * $Id: lqr.c,v 1.17 1997/08/25 00:29:18 brian Exp $
21 *
22 * o LQR based on RFC1333
23 *
24 * TODO:
25 * o LQM policy
26 * o Allow user to configure LQM method and interval.
27 */
28#include "fsm.h"
29#include "lcpproto.h"
30#include "lqr.h"
31#include "hdlc.h"
32#include "lcp.h"
33#include "loadalias.h"
34#include "vars.h"
35#include "main.h"
36
37struct pppTimer LqrTimer;
38
39static u_long lastpeerin = (u_long) - 1;
40
41static int lqmmethod;
42static int echoseq;
43static int gotseq;
44static int lqrsendcnt;
45
46struct echolqr {
47 u_long magic;
48 u_long signature;
49 u_long sequence;
50};
51
52#define SIGNATURE 0x594e4f54
53
54static void
55SendEchoReq()
56{
57 struct fsm *fp = &LcpFsm;
58 struct echolqr *lqr, lqrdata;
59
60 if (fp->state == ST_OPENED) {
61 lqr = &lqrdata;
62 lqr->magic = htonl(LcpInfo.want_magic);
63 lqr->signature = htonl(SIGNATURE);
64 LogPrintf(LogLQM, "Send echo LQR [%d]\n", echoseq);
65 lqr->sequence = htonl(echoseq++);
66 FsmOutput(fp, CODE_ECHOREQ, fp->reqid++,
67 (u_char *) lqr, sizeof(struct echolqr));
68 }
69}
70
71void
72RecvEchoLqr(struct mbuf * bp)
73{
74 struct echolqr *lqr;
75 u_long seq;
76
77 if (plength(bp) == sizeof(struct echolqr)) {
78 lqr = (struct echolqr *) MBUF_CTOP(bp);
79 if (htonl(lqr->signature) == SIGNATURE) {
80 seq = ntohl(lqr->sequence);
81 LogPrintf(LogLQM, "Got echo LQR [%d]\n", ntohl(lqr->sequence));
82 gotseq = seq;
83 }
84 }
85}
86
87void
88LqrChangeOrder(struct lqrdata * src, struct lqrdata * dst)
89{
90 u_long *sp, *dp;
91 int n;
92
93 sp = (u_long *) src;
94 dp = (u_long *) dst;
95 for (n = 0; n < sizeof(struct lqrdata) / sizeof(u_long); n++)
96 *dp++ = ntohl(*sp++);
97}
98
99static void
100SendLqrReport()
101{
102 struct mbuf *bp;
103
104 StopTimer(&LqrTimer);
105
106 if (lqmmethod & LQM_LQR) {
107 if (lqrsendcnt > 5) {
108
109 /*
110 * XXX: Should implement LQM strategy
111 */
112 LogPrintf(LogPHASE, "** 1 Too many ECHO packets are lost. **\n");
113 lqmmethod = 0; /* Prevent rcursion via LcpClose() */
114 reconnect(RECON_TRUE);
115 LcpClose();
116 } else {
117 bp = mballoc(sizeof(struct lqrdata), MB_LQR);
118 HdlcOutput(PRI_LINK, PROTO_LQR, bp);
119 lqrsendcnt++;
120 }
121 } else if (lqmmethod & LQM_ECHO) {
122 if (echoseq - gotseq > 5) {
123 LogPrintf(LogPHASE, "** 2 Too many ECHO packets are lost. **\n");
124 lqmmethod = 0; /* Prevent rcursion via LcpClose() */
125 reconnect(RECON_TRUE);
126 LcpClose();
127 } else
128 SendEchoReq();
129 }
130 if (lqmmethod && Enabled(ConfLqr))
131 StartTimer(&LqrTimer);
132}
133
134void
135LqrInput(struct mbuf * bp)
136{
137 int len;
138 u_char *cp;
139 struct lqrdata *lqr;
140
141 len = plength(bp);
142 if (len != sizeof(struct lqrdata)) {
143 pfree(bp);
144 return;
145 }
146 if (!Acceptable(ConfLqr)) {
147 bp->offset -= 2;
148 bp->cnt += 2;
149
150 cp = MBUF_CTOP(bp);
151 LcpSendProtoRej(cp, bp->cnt);
152 } else {
153 cp = MBUF_CTOP(bp);
154 lqr = (struct lqrdata *) cp;
155 if (ntohl(lqr->MagicNumber) != LcpInfo.his_magic) {
156 LogPrintf(LogERROR, "LqrInput: magic %x != expecting %x\n",
157 ntohl(lqr->MagicNumber), LcpInfo.his_magic);
158 pfree(bp);
159 return;
160 }
161
162 /*
163 * Convert byte order and save into our strage
164 */
165 LqrChangeOrder(lqr, &HisLqrData);
166 LqrDump("LqrInput", &HisLqrData);
167 lqrsendcnt = 0; /* we have received LQR from peer */
168
169 /*
170 * Generate LQR responce to peer, if i) We are not running LQR timer. ii)
171 * Two successive LQR's PeerInLQRs are same.
172 */
173 if (LqrTimer.load == 0 || lastpeerin == HisLqrData.PeerInLQRs) {
174 lqmmethod |= LQM_LQR;
175 SendLqrReport();
176 }
177 lastpeerin = HisLqrData.PeerInLQRs;
178 }
179 pfree(bp);
180}
181
182/*
183 * When LCP is reached to opened state, We'll start LQM activity.
184 */
185void
186StartLqm()
187{
188 struct lcpstate *lcp = &LcpInfo;
189 int period;
190
191 lqrsendcnt = 0; /* start waiting all over for ECHOs */
192 echoseq = 0;
193 gotseq = 0;
194
195 lqmmethod = LQM_ECHO;
196 if (Enabled(ConfLqr))
197 lqmmethod |= LQM_LQR;
198 StopTimer(&LqrTimer);
199 LogPrintf(LogLQM, "LQM method = %d\n", lqmmethod);
200
201 if (lcp->his_lqrperiod || lcp->want_lqrperiod) {
202
203 /*
204 * We need to run timer. Let's figure out period.
205 */
206 period = lcp->his_lqrperiod ? lcp->his_lqrperiod : lcp->want_lqrperiod;
207 StopTimer(&LqrTimer);
208 LqrTimer.state = TIMER_STOPPED;
209 LqrTimer.load = period * SECTICKS / 100;
210 LqrTimer.func = SendLqrReport;
211 SendLqrReport();
212 StartTimer(&LqrTimer);
213 LogPrintf(LogLQM, "Will send LQR every %d.%d secs\n",
214 period / 100, period % 100);
215 } else {
216 LogPrintf(LogLQM, "LQR is not activated.\n");
217 }
218}
219
220void
221StopLqrTimer()
222{
223 StopTimer(&LqrTimer);
224}
225
226void
227StopLqr(int method)
228{
229 LogPrintf(LogLQM, "StopLqr method = %x\n", method);
230
231 if (method == LQM_LQR)
232 LogPrintf(LogLQM, "Stop sending LQR, Use LCP ECHO instead.\n");
233 if (method == LQM_ECHO)
234 LogPrintf(LogLQM, "Stop sending LCP ECHO.\n");
235 lqmmethod &= ~method;
236 if (lqmmethod)
237 SendLqrReport();
238 else
239 StopTimer(&LqrTimer);
240}
241
242void
243LqrDump(char *message, struct lqrdata * lqr)
244{
245 if (LogIsKept(LogLQM)) {
246 LogPrintf(LogLQM, "%s:\n", message);
247 LogPrintf(LogLQM, " Magic: %08x LastOutLQRs: %08x\n",
248 lqr->MagicNumber, lqr->LastOutLQRs);
249 LogPrintf(LogLQM, " LastOutPackets: %08x LastOutOctets: %08x\n",
250 lqr->LastOutPackets, lqr->LastOutOctets);
251 LogPrintf(LogLQM, " PeerInLQRs: %08x PeerInPackets: %08x\n",
252 lqr->PeerInLQRs, lqr->PeerInPackets);
253 LogPrintf(LogLQM, " PeerInDiscards: %08x PeerInErrors: %08x\n",
254 lqr->PeerInDiscards, lqr->PeerInErrors);
255 LogPrintf(LogLQM, " PeerInOctets: %08x PeerOutLQRs: %08x\n",
256 lqr->PeerInOctets, lqr->PeerOutLQRs);
257 LogPrintf(LogLQM, " PeerOutPackets: %08x PeerOutOctets: %08x\n",
258 lqr->PeerOutPackets, lqr->PeerOutOctets);
259 }
260}