diff options
author | Archie Cobbs <archie@FreeBSD.org> | 2000-07-25 00:23:19 +0000 |
---|---|---|
committer | Archie Cobbs <archie@FreeBSD.org> | 2000-07-25 00:23:19 +0000 |
commit | 678f9e335efa5d4759d235773b06e7a5a4c91236 (patch) | |
tree | 75d18925a828154f6911ba0696d9298af2bd1b9a | |
parent | c27eebfde8c04a4e0d30bde64ad064898e2eb8c9 (diff) | |
download | src-678f9e335efa5d4759d235773b06e7a5a4c91236.tar.gz src-678f9e335efa5d4759d235773b06e7a5a4c91236.zip |
Notes
-rw-r--r-- | sys/netgraph/ng_pptpgre.c | 79 | ||||
-rw-r--r-- | sys/netgraph/ng_pptpgre.h | 6 |
2 files changed, 59 insertions, 26 deletions
diff --git a/sys/netgraph/ng_pptpgre.c b/sys/netgraph/ng_pptpgre.c index 9d280953cb0f..3a361f7c1493 100644 --- a/sys/netgraph/ng_pptpgre.c +++ b/sys/netgraph/ng_pptpgre.c @@ -116,7 +116,7 @@ struct greheader { /* All times are scaled by this (PPTP_TIME_SCALE time units = 1 sec.) */ #define PPTP_TIME_SCALE 1000 /* milliseconds */ -typedef u_int32_t pptptime_t; +typedef u_int64_t pptptime_t; /* Acknowledgment timeout parameters and functions */ #define PPTP_XMIT_WIN 16 /* max xmit window */ @@ -144,6 +144,10 @@ struct ng_pptpgre_ackp { node_p *rackTimerPtr; /* recv ack timer pointer */ u_int32_t winAck; /* seq when xmitWin will grow */ pptptime_t timeSent[PPTP_XMIT_WIN]; +#ifdef DEBUG_RAT + pptptime_t timerStart; + pptptime_t timerLength; +#endif }; /* When we recieve a packet, we wait to see if there's an outgoing packet @@ -493,7 +497,7 @@ ng_pptpgre_xmit(node_p node, struct mbuf *m, meta_p meta) priv->stats.xmitLoneAcks++; /* Build GRE header */ - ((u_int32_t *) gre)[0] = htonl(PPTP_INIT_VALUE); + ((u_int32_t *)gre)[0] = htonl(PPTP_INIT_VALUE); gre->length = (m != NULL) ? htons((u_short)m->m_pkthdr.len) : 0; gre->cid = htons(priv->conf.peerCid); @@ -504,15 +508,13 @@ ng_pptpgre_xmit(node_p node, struct mbuf *m, meta_p meta) = ng_pptpgre_time(node); priv->xmitSeq++; gre->data[0] = htonl(priv->xmitSeq); - if (priv->xmitSeq == priv->recvAck + 1) - ng_pptpgre_start_recv_ack_timer(node); } /* Include acknowledgement (and stop send ack timer) if needed */ - if (PPTP_SEQ_DIFF(priv->xmitAck, priv->recvSeq) < 0) { + if (priv->conf.enableAlwaysAck || priv->xmitAck != priv->recvSeq) { gre->hasAck = 1; + gre->data[gre->hasSeq] = htonl(priv->recvSeq); priv->xmitAck = priv->recvSeq; - gre->data[gre->hasSeq] = htonl(priv->xmitAck); a->sackTimerPtr = NULL; } @@ -521,6 +523,7 @@ ng_pptpgre_xmit(node_p node, struct mbuf *m, meta_p meta) if (m == NULL) { MGETHDR(m, M_DONTWAIT, MT_DATA); if (m == NULL) { + priv->stats.memoryFailures++; NG_FREE_META(meta); return (ENOBUFS); } @@ -530,6 +533,7 @@ ng_pptpgre_xmit(node_p node, struct mbuf *m, meta_p meta) M_PREPEND(m, grelen, M_NOWAIT); if (m == NULL || (m->m_len < grelen && (m = m_pullup(m, grelen)) == NULL)) { + priv->stats.memoryFailures++; NG_FREE_META(meta); return (ENOBUFS); } @@ -542,6 +546,10 @@ ng_pptpgre_xmit(node_p node, struct mbuf *m, meta_p meta) /* Deliver packet */ NG_SEND_DATA(error, priv->lower, m, meta); + + /* Start send ACK timer */ + if (error == 0 && gre->hasSeq && priv->xmitSeq == priv->recvAck + 1) + ng_pptpgre_start_recv_ack_timer(node); return (error); } @@ -572,6 +580,7 @@ bad: /* Safely pull up the complete IP+GRE headers */ if (m->m_len < sizeof(*ip) + sizeof(*gre) && (m = m_pullup(m, sizeof(*ip) + sizeof(*gre))) == NULL) { + priv->stats.memoryFailures++; NG_FREE_META(meta); return (ENOBUFS); } @@ -579,6 +588,7 @@ bad: iphlen = ip->ip_hl << 2; if (m->m_len < iphlen + sizeof(*gre)) { if ((m = m_pullup(m, iphlen + sizeof(*gre))) == NULL) { + priv->stats.memoryFailures++; NG_FREE_META(meta); return (ENOBUFS); } @@ -592,6 +602,7 @@ bad: } if (m->m_len < iphlen + grelen) { if ((m = m_pullup(m, iphlen + grelen)) == NULL) { + priv->stats.memoryFailures++; NG_FREE_META(meta); return (ENOBUFS); } @@ -656,7 +667,9 @@ bad: } /* Stop/(re)start receive ACK timer as necessary */ - ng_pptpgre_start_recv_ack_timer(node); + a->rackTimerPtr = NULL; + if (priv->recvAck != priv->xmitSeq) + ng_pptpgre_start_recv_ack_timer(node); } badAck: @@ -682,8 +695,8 @@ badAck: /* Take half of the estimated round trip time */ maxWait = (a->rtt >> 1); - /* If too soon, just send one right now */ - if (!priv->conf.enableDelayedAck) + /* If delayed ACK is disabled, send it now */ + if (!priv->conf.enableDelayedAck || maxWait == 0) ng_pptpgre_xmit(node, NULL, NULL); else { /* send the ack later */ if (maxWait > PPTP_MAX_ACK_DELAY) @@ -721,29 +734,31 @@ ng_pptpgre_start_recv_ack_timer(node_p node) { const priv_p priv = node->private; struct ng_pptpgre_ackp *const a = &priv->ackp; - int remain; - - /* "Stop" current recv ack timer, if any */ - a->rackTimerPtr = NULL; - - /* Are we waiting for an acknowlegement? */ - if (priv->recvAck == priv->xmitSeq) - return; + int remain, ticks; /* Compute how long until oldest unack'd packet times out, and reset the timer to that time. */ remain = (a->timeSent[0] + a->ato) - ng_pptpgre_time(node); if (remain < 0) remain = 0; +#ifdef DEBUG_RAT + a->timerLength = remain; + a->timerStart = ng_pptpgre_time(node); +#endif /* Start new timer */ MALLOC(a->rackTimerPtr, node_p *, sizeof(node_p), M_NETGRAPH, M_NOWAIT); - if (a->rackTimerPtr == NULL) + if (a->rackTimerPtr == NULL) { + priv->stats.memoryFailures++; return; /* XXX potential hang here */ + } *a->rackTimerPtr = node; /* insures the correct timeout event */ node->refs++; + + /* Be conservative: timeout() can return up to 1 tick early */ + ticks = (((remain * hz) + PPTP_TIME_SCALE - 1) / PPTP_TIME_SCALE) + 1; a->rackTimer = timeout(ng_pptpgre_recv_ack_timeout, - a->rackTimerPtr, remain * hz / PPTP_TIME_SCALE); + a->rackTimerPtr, ticks); } /* @@ -783,6 +798,13 @@ ng_pptpgre_recv_ack_timeout(void *arg) if (a->ato < PPTP_MIN_TIMEOUT) a->ato = PPTP_MIN_TIMEOUT; +#ifdef DEBUG_RAT + log(LOG_DEBUG, + "RAT now=%d seq=0x%x sent=%d tstart=%d tlen=%d ato=%d\n", + (int)ng_pptpgre_time(node), priv->recvAck + 1, + (int)a->timeSent[0], (int)a->timerStart, (int)a->timerLength, a->ato); +#endif + /* Reset ack and sliding window */ priv->recvAck = priv->xmitSeq; /* pretend we got the ack */ a->xmitWin = (a->xmitWin + 1) / 2; /* shrink transmit window */ @@ -799,16 +821,22 @@ ng_pptpgre_start_send_ack_timer(node_p node, long ackTimeout) { const priv_p priv = node->private; struct ng_pptpgre_ackp *const a = &priv->ackp; + int ticks; /* Start new timer */ KASSERT(a->sackTimerPtr == NULL, ("%s: sackTimer", __FUNCTION__)); MALLOC(a->sackTimerPtr, node_p *, sizeof(node_p), M_NETGRAPH, M_NOWAIT); - if (a->sackTimerPtr == NULL) + if (a->sackTimerPtr == NULL) { + priv->stats.memoryFailures++; return; /* XXX potential hang here */ + } *a->sackTimerPtr = node; node->refs++; + + /* Be conservative: timeout() can return up to 1 tick early */ + ticks = (((ackTimeout * hz) + PPTP_TIME_SCALE - 1) / PPTP_TIME_SCALE); a->sackTimer = timeout(ng_pptpgre_send_ack_timeout, - a->sackTimerPtr, ackTimeout * hz / PPTP_TIME_SCALE); + a->sackTimerPtr, ticks); } /* @@ -896,15 +924,16 @@ ng_pptpgre_time(node_p node) { const priv_p priv = node->private; struct timeval tv; + pptptime_t t; - getmicrouptime(&tv); + microuptime(&tv); if (tv.tv_sec < priv->startTime.tv_sec || (tv.tv_sec == priv->startTime.tv_sec && tv.tv_usec < priv->startTime.tv_usec)) return (0); timevalsub(&tv, &priv->startTime); - tv.tv_sec *= PPTP_TIME_SCALE; - tv.tv_usec /= 1000000 / PPTP_TIME_SCALE; - return(tv.tv_sec + tv.tv_usec); + t = (pptptime_t)tv.tv_sec * PPTP_TIME_SCALE; + t += (pptptime_t)tv.tv_usec / (1000000 / PPTP_TIME_SCALE); + return(t); } diff --git a/sys/netgraph/ng_pptpgre.h b/sys/netgraph/ng_pptpgre.h index 8488a8dc559e..f8fb7c34918f 100644 --- a/sys/netgraph/ng_pptpgre.h +++ b/sys/netgraph/ng_pptpgre.h @@ -45,7 +45,7 @@ /* Node type name and magic cookie */ #define NG_PPTPGRE_NODE_TYPE "pptpgre" -#define NGM_PPTPGRE_COOKIE 942783546 +#define NGM_PPTPGRE_COOKIE 942783547 /* Hook names */ #define NG_PPTPGRE_HOOK_UPPER "upper" /* to upper layers */ @@ -55,6 +55,7 @@ struct ng_pptpgre_conf { u_char enabled; /* enables traffic flow */ u_char enableDelayedAck;/* enables delayed acks */ + u_char enableAlwaysAck;/* always include ack with data */ u_int16_t cid; /* my call id */ u_int16_t peerCid; /* peer call id */ u_int16_t recvWin; /* peer recv window size */ @@ -67,6 +68,7 @@ struct ng_pptpgre_conf { { \ { "enabled", &ng_parse_int8_type }, \ { "enableDelayedAck", &ng_parse_int8_type }, \ + { "enableAlwaysAck", &ng_parse_int8_type }, \ { "cid", &ng_parse_int16_type }, \ { "peerCid", &ng_parse_int16_type }, \ { "recvWin", &ng_parse_int16_type }, \ @@ -92,6 +94,7 @@ struct ng_pptpgre_stats { u_int32_t recvDuplicates; /* packets rec'd with duplicate seq # */ u_int32_t recvLoneAcks; /* ack-only packets rec'd */ u_int32_t recvAckTimeouts; /* times peer failed to ack in time */ + u_int32_t memoryFailures; /* times we couldn't allocate memory */ }; /* Keep this in sync with the above structure definition */ @@ -112,6 +115,7 @@ struct ng_pptpgre_stats { { "recvDuplicates", &ng_parse_int32_type }, \ { "recvLoneAcks", &ng_parse_int32_type }, \ { "recvAckTimeouts", &ng_parse_int32_type }, \ + { "memoryFailures", &ng_parse_int32_type }, \ { NULL } \ } \ } |