diff options
author | brian <brian@FreeBSD.org> | 1998-01-10 01:55:11 +0000 |
---|---|---|
committer | brian <brian@FreeBSD.org> | 1998-01-10 01:55:11 +0000 |
commit | e0d5cac89839c8ee905983e98064022932b8ccb8 (patch) | |
tree | c3e0aee50601f692156073c8c2ce5e0fb0e2aca3 | |
parent | bf1b24637d5c06e5fc72dd85eaa43f135d74f5eb (diff) | |
download | FreeBSD-src-e0d5cac89839c8ee905983e98064022932b8ccb8.zip FreeBSD-src-e0d5cac89839c8ee905983e98064022932b8ccb8.tar.gz |
Implement Reset{Req,Ack} properly, as per rfc 1962.
(I completely mis-read the rfc last time 'round!)
This means:
o Better CCP/WARN Reset diagnostics.
o After we've sent a REQ and before we've received an ACK, we drop
incoming compressed data and send another REQ.
o Before sending an ACK, re-sequence all pending PRI_NORMAL data in
the modem queue so that pending packets won't get to the peer
*after* the ResetAck.
o Send ACKs with the `identifier' from the REQ frame.
o After we've received a correct ACK, duplicate ACKs are ok (and will
reset our history).
o Incorrect ACKs (not matching the last REQ) are moaned about and dropped.
Also,
o Calculate the correct FCS after compressing a packet. DEFLATE
*may* produce an mbuf with more than a single link in the chain,
but HdlcOutput didn't know how to calculate the FCS :-(
o Make `struct fsm'::reqid a u_char, not an int.
This fix will prevent us from sending id `255' 2,000,000,000 times
before wrapping to `0' for another 2,000,000,000 sends :-/
o Bump the version number a little.
The end result: DEFLATE now works over an unreliable link layer.
I can txfr a 1.5Mb kernel over a (rather bad) null-modem
cable at an average of 21679 bytes per second using rcp.
Repeat after me: Don't test compression using a loopback ppp/tcp setup as
we never lose packets and therefore never have to reset!
-rw-r--r-- | usr.sbin/ppp/ccp.c | 34 | ||||
-rw-r--r-- | usr.sbin/ppp/ccp.h | 7 | ||||
-rw-r--r-- | usr.sbin/ppp/deflate.c | 25 | ||||
-rw-r--r-- | usr.sbin/ppp/fsm.c | 18 | ||||
-rw-r--r-- | usr.sbin/ppp/fsm.h | 4 | ||||
-rw-r--r-- | usr.sbin/ppp/hdlc.c | 17 | ||||
-rw-r--r-- | usr.sbin/ppp/modem.c | 12 | ||||
-rw-r--r-- | usr.sbin/ppp/modem.h | 3 | ||||
-rw-r--r-- | usr.sbin/ppp/vars.c | 6 |
9 files changed, 84 insertions, 42 deletions
diff --git a/usr.sbin/ppp/ccp.c b/usr.sbin/ppp/ccp.c index e49cf3a..16e86b2 100644 --- a/usr.sbin/ppp/ccp.c +++ b/usr.sbin/ppp/ccp.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: ccp.c,v 1.26 1997/12/24 09:28:52 brian Exp $ + * $Id: ccp.c,v 1.27 1998/01/04 20:25:39 brian Exp $ * * TODO: * o Support other compression protocols @@ -43,7 +43,7 @@ #include "pred.h" #include "deflate.h" -struct ccpstate CcpInfo = { -1, -1 }; +struct ccpstate CcpInfo = { -1, -1, -1, -1 }; static void CcpSendConfigReq(struct fsm *); static void CcpSendTerminateReq(struct fsm *); @@ -146,6 +146,7 @@ ccpstateInit(void) out_algorithm = -1; memset(&CcpInfo, '\0', sizeof CcpInfo); CcpInfo.his_proto = CcpInfo.my_proto = -1; + CcpInfo.reset_sent = CcpInfo.last_reset = -1; } void @@ -189,7 +190,9 @@ CcpSendConfigReq(struct fsm *fp) void CcpSendResetReq(struct fsm *fp) { - LogPrintf(LogCCP, "CcpSendResetReq\n"); + LogPrintf(LogCCP, "SendResetReq(%d)\n", fp->reqid); + CcpInfo.reset_sent = fp->reqid; + CcpInfo.last_reset = -1; FsmOutput(fp, CODE_RESETREQ, fp->reqid, NULL, 0); } @@ -378,8 +381,24 @@ CcpInput(struct mbuf *bp) } void -CcpResetInput() +CcpResetInput(u_char id) { + if (CcpInfo.reset_sent != -1) { + if (id != CcpInfo.reset_sent) { + LogPrintf(LogWARN, "CCP: Incorrect ResetAck (id %d, not %d) ignored\n", + id, CcpInfo.reset_sent); + return; + } + /* Whaddaya know - a correct reset ack */ + } else if (id == CcpInfo.last_reset) + LogPrintf(LogCCP, "Duplicate ResetAck (resetting again)\n"); + else { + LogPrintf(LogWARN, "CCP: Unexpected ResetAck (id %d) ignored\n", id); + return; + } + + CcpInfo.last_reset = CcpInfo.reset_sent; + CcpInfo.reset_sent = -1; if (in_algorithm >= 0 && in_algorithm < NALGORITHMS) (*algorithm[in_algorithm]->i.Reset)(); } @@ -395,7 +414,12 @@ CcpOutput(int pri, u_short proto, struct mbuf *m) struct mbuf * CompdInput(u_short *proto, struct mbuf *m) { - if (in_algorithm >= 0 && in_algorithm < NALGORITHMS) + if (CcpInfo.reset_sent != -1) { + /* Send another REQ and put the packet in the bit bucket */ + LogPrintf(LogCCP, "ReSendResetReq(%d)\n", CcpInfo.reset_sent); + FsmOutput(&CcpFsm, CODE_RESETREQ, CcpInfo.reset_sent, NULL, 0); + pfree(m); + } else if (in_algorithm >= 0 && in_algorithm < NALGORITHMS) return (*algorithm[in_algorithm]->i.Read)(proto, m); return NULL; } diff --git a/usr.sbin/ppp/ccp.h b/usr.sbin/ppp/ccp.h index 840e2da..1be021c 100644 --- a/usr.sbin/ppp/ccp.h +++ b/usr.sbin/ppp/ccp.h @@ -15,7 +15,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: ccp.h,v 1.11 1997/12/03 23:27:55 brian Exp $ + * $Id: ccp.h,v 1.12 1998/01/04 20:25:41 brian Exp $ * * TODO: */ @@ -39,6 +39,9 @@ struct ccpstate { u_long his_proto; /* peer's compression protocol */ u_long my_proto; /* our compression protocol */ + int reset_sent; /* If != -1, ignore compressed 'till ack */ + int last_reset; /* We can receive more (dups) w/ this id */ + u_long his_reject; /* Request codes rejected by peer */ u_long my_reject; /* Request codes I have rejected */ @@ -83,7 +86,7 @@ extern void CcpUp(void); extern void CcpOpen(void); extern void CcpInit(void); extern int ReportCcpStatus(struct cmdargs const *); -extern void CcpResetInput(void); +extern void CcpResetInput(u_char); extern int CcpOutput(int, u_short, struct mbuf *); extern struct mbuf *CompdInput(u_short *, struct mbuf *); extern void CcpDictSetup(u_short, struct mbuf *); diff --git a/usr.sbin/ppp/deflate.c b/usr.sbin/ppp/deflate.c index 3adf2e9..1897d3a 100644 --- a/usr.sbin/ppp/deflate.c +++ b/usr.sbin/ppp/deflate.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: deflate.c,v 1.4 1997/12/21 12:11:04 brian Exp $ + * $Id: deflate.c,v 1.5 1997/12/28 02:17:06 brian Exp $ */ #include <sys/param.h> @@ -50,7 +50,7 @@ /* Our state */ struct deflate_state { u_short seqno; - int dodgy_seqno; + int uncomp_rec; z_stream cx; }; @@ -66,7 +66,7 @@ static void DeflateResetOutput(void) { OutputState.seqno = 0; - OutputState.dodgy_seqno = 0; + OutputState.uncomp_rec = 0; deflateReset(&OutputState.cx); LogPrintf(LogCCP, "Deflate: Output channel reset\n"); } @@ -192,7 +192,7 @@ static void DeflateResetInput(void) { InputState.seqno = 0; - InputState.dodgy_seqno = 0; + InputState.uncomp_rec = 0; inflateReset(&InputState.cx); LogPrintf(LogCCP, "Deflate: Input channel reset\n"); } @@ -214,7 +214,12 @@ DeflateInput(u_short *proto, struct mbuf *mi) seq = (hdr[0] << 8) + hdr[1]; LogPrintf(LogDEBUG, "DeflateInput: Seq %d\n", seq); if (seq != InputState.seqno) { - if (InputState.dodgy_seqno && seq < InputState.seqno) + if (seq <= InputState.uncomp_rec) + /* + * So the peer's started at zero again - fine ! If we're wrong, + * inflate() will fail. This is better than getting into a loop + * trying to get a ResetReq to a busy sender. + */ InputState.seqno = seq; else { LogPrintf(LogERROR, "DeflateInput: Seq error: Got %d, expected %d\n", @@ -225,7 +230,7 @@ DeflateInput(u_short *proto, struct mbuf *mi) } } InputState.seqno++; - InputState.dodgy_seqno = 0; + InputState.uncomp_rec = 0; /* Allocate an output mbuf */ mo_head = mo = mballoc(DEFLATE_CHUNK_LEN, MB_IPIN); @@ -420,6 +425,7 @@ DeflateDictSetup(u_short proto, struct mbuf *mi) CcpInfo.uncompin += len; InputState.seqno++; + InputState.uncomp_rec++; mbfree(mi_head); /* lose our allocated ``head'' buf */ } @@ -533,13 +539,6 @@ DeflateInitInput(void) if (inflateInit2(&InputState.cx, -iWindowSize) != Z_OK) return 0; DeflateResetInput(); - /* - * When we begin, we may start adding to our dictionary before the - * peer does. If `dodgy_seqno' is set, we'll allow the peer to send - * us a seqno that's too small and just adjust seqno accordingly - - * deflate is a sliding window compressor ! - */ - InputState.dodgy_seqno = 1; return 1; } diff --git a/usr.sbin/ppp/fsm.c b/usr.sbin/ppp/fsm.c index 3a949f7..1dd5bef 100644 --- a/usr.sbin/ppp/fsm.c +++ b/usr.sbin/ppp/fsm.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: fsm.c,v 1.24 1997/12/13 02:37:23 brian Exp $ + * $Id: fsm.c,v 1.25 1997/12/24 09:28:58 brian Exp $ * * TODO: * o Refer loglevel for log output @@ -724,18 +724,24 @@ FsmRecvTimeRemain(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) static void FsmRecvResetReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) { - LogPrintf(fp->LogLevel, "RecvResetReq\n"); + LogPrintf(fp->LogLevel, "RecvResetReq(%d)\n", lhp->id); CcpRecvResetReq(fp); - LogPrintf(fp->LogLevel, "SendResetAck\n"); - FsmOutput(fp, CODE_RESETACK, fp->reqid, NULL, 0); + /* + * All sendable compressed packets are queued in the PRI_NORMAL modem + * output queue.... dump 'em to the priority queue so that they arrive + * at the peer before our ResetAck. + */ + SequenceQueues(); + LogPrintf(fp->LogLevel, "SendResetAck(%d)\n", lhp->id); + FsmOutput(fp, CODE_RESETACK, lhp->id, NULL, 0); pfree(bp); } static void FsmRecvResetAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) { - LogPrintf(fp->LogLevel, "RecvResetAck\n"); - CcpResetInput(); + LogPrintf(fp->LogLevel, "RecvResetAck(%d)\n", lhp->id); + CcpResetInput(lhp->id); fp->reqid++; pfree(bp); } diff --git a/usr.sbin/ppp/fsm.h b/usr.sbin/ppp/fsm.h index d3527af..07ddb3b 100644 --- a/usr.sbin/ppp/fsm.h +++ b/usr.sbin/ppp/fsm.h @@ -15,7 +15,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: fsm.h,v 1.12 1997/11/22 03:37:32 brian Exp $ + * $Id: fsm.h,v 1.13 1997/12/03 10:23:47 brian Exp $ * * TODO: */ @@ -52,7 +52,7 @@ struct fsm { u_short max_code; int open_mode; int state; /* State of the machine */ - int reqid; /* Next request id */ + u_char reqid; /* Next request id */ int restart; /* Restart counter value */ int maxconfig; diff --git a/usr.sbin/ppp/hdlc.c b/usr.sbin/ppp/hdlc.c index f56bc50..db0dc87 100644 --- a/usr.sbin/ppp/hdlc.c +++ b/usr.sbin/ppp/hdlc.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: hdlc.c,v 1.25 1997/12/24 09:29:00 brian Exp $ + * $Id: hdlc.c,v 1.26 1998/01/06 00:58:31 brian Exp $ * * TODO: */ @@ -223,12 +223,13 @@ HdlcOutput(int pri, u_short proto, struct mbuf * bp) LqrChangeOrder(lqr, (struct lqrdata *) (MBUF_CTOP(bp))); } if (!DEV_IS_SYNC) { - fcs = HdlcFcs(INITFCS, MBUF_CTOP(mhp), mhp->cnt); - fcs = HdlcFcs(fcs, MBUF_CTOP(bp), bp->cnt); + mfcs->cnt = 0; + fcs = HdlcFcsBuf(INITFCS, mhp); fcs = ~fcs; cp = MBUF_CTOP(mfcs); *cp++ = fcs & 0377; /* Low byte first!! */ *cp++ = fcs >> 8; + mfcs->cnt = 2; } LogDumpBp(LogHDLC, "HdlcOutput", mhp); for (statp = ProtocolStat; statp->number; statp++) @@ -381,11 +382,11 @@ DecodePacket(u_short proto, struct mbuf * bp) * If proto isn't PROTO_COMPD, we still want to pass it to the * decompression routines so that the dictionary's updated */ - if (proto == PROTO_COMPD) { - if ((bp = CompdInput(&proto, bp)) == NULL) - return; - } else if ((proto & 0xfff1) == 0x21) /* Network Layer protocol */ - if (CcpFsm.state == ST_OPENED) + if (CcpFsm.state == ST_OPENED) + if (proto == PROTO_COMPD) { + if ((bp = CompdInput(&proto, bp)) == NULL) + return; + } else if ((proto & 0xfff1) == 0x21) /* Network Layer protocol */ CcpDictSetup(proto, bp); switch (proto) { diff --git a/usr.sbin/ppp/modem.c b/usr.sbin/ppp/modem.c index b3f03b9..40183a1 100644 --- a/usr.sbin/ppp/modem.c +++ b/usr.sbin/ppp/modem.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: modem.c,v 1.72 1997/12/28 02:56:43 brian Exp $ + * $Id: modem.c,v 1.73 1997/12/30 23:22:31 brian Exp $ * * TODO: */ @@ -94,7 +94,7 @@ Enqueue(struct mqueue * queue, struct mbuf * bp) } struct mbuf * -Dequeue(struct mqueue * queue) +Dequeue(struct mqueue *queue) { struct mbuf *bp; @@ -112,6 +112,14 @@ Dequeue(struct mqueue * queue) return (bp); } +void +SequenceQueues() +{ + LogPrintf(LogDEBUG, "SequenceQueues\n"); + while (OutputQueues[PRI_NORMAL].qlen) + Enqueue(OutputQueues + PRI_LINK, Dequeue(OutputQueues + PRI_NORMAL)); +} + static struct speeds { int nspeed; speed_t speed; diff --git a/usr.sbin/ppp/modem.h b/usr.sbin/ppp/modem.h index fae70e5..3419a6f 100644 --- a/usr.sbin/ppp/modem.h +++ b/usr.sbin/ppp/modem.h @@ -15,7 +15,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: modem.h,v 1.13 1997/11/08 00:28:10 brian Exp $ + * $Id: modem.h,v 1.14 1997/11/22 03:37:41 brian Exp $ * * TODO: */ @@ -38,5 +38,6 @@ extern void HangupModem(int); extern int ShowModemStatus(struct cmdargs const *); extern void Enqueue(struct mqueue *, struct mbuf *); extern struct mbuf *Dequeue(struct mqueue *); +extern void SequenceQueues(void); extern void ModemAddInOctets(int); extern void ModemAddOutOctets(int); diff --git a/usr.sbin/ppp/vars.c b/usr.sbin/ppp/vars.c index 494244e..5781749 100644 --- a/usr.sbin/ppp/vars.c +++ b/usr.sbin/ppp/vars.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: vars.c,v 1.41 1997/12/21 03:16:17 brian Exp $ + * $Id: vars.c,v 1.42 1997/12/29 22:23:12 brian Exp $ * */ #include <sys/param.h> @@ -38,8 +38,8 @@ #include "vars.h" #include "auth.h" -char VarVersion[] = "PPP Version 1.6"; -char VarLocalVersion[] = "$Date: 1997/12/21 03:16:17 $"; +char VarVersion[] = "PPP Version 1.65"; +char VarLocalVersion[] = "$Date: 1997/12/29 22:23:12 $"; int Utmp = 0; int ipInOctets = 0; int ipOutOctets = 0; |