Add 'enableWindowing' configuration knob to the ng_pptpgre(4) netgraph node.

Submitted by:	Michael Bretterklieber <mbretter@a-quadrat.at>
MFC after:	2 weeks
This commit is contained in:
Archie Cobbs 2004-04-26 14:26:54 +00:00
parent d33f4987f6
commit 922ee196d9
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=128657
3 changed files with 59 additions and 34 deletions

View File

@ -92,6 +92,7 @@ struct ng_pptpgre_conf {
u_char enabled; /* enables traffic flow */
u_char enableDelayedAck; /* enables delayed acks */
u_char enableAlwaysAck; /* always send ack with data */
u_char enableWindowing; /* enable windowing algorithm */
u_int16_t cid; /* my call id */
u_int16_t peerCid; /* peer call id */
u_int16_t recvWin; /* peer recv window size */
@ -110,6 +111,14 @@ is a useful optimization and should generally be turned on.
.Va enableAlwaysAck
field enables sending acknowledgements with every data packet, which
is probably helpful as well.
.Pp
.Va enableWindowing
enables the PPTP packet windowing mechanism specified by the protocol.
Disabling this will cause the node to violate the protocol, possibly
confusing other PPTP peers, but often results in better performance.
The windowing mechanism is a design error in the PPTP protocol;
L2TP, the successor to PPTP, removes it.
.Pp
The remaining fields are as supplied by the PPTP virtual call setup process.
.It Dv NGM_PPTPGRE_GET_CONFIG
Returns the current configuration as a

View File

@ -477,13 +477,16 @@ ng_pptpgre_xmit(node_p node, item_p item)
/* Check if there's data */
if (m != NULL) {
/* Is our transmit window full? */
if ((u_int32_t)PPTP_SEQ_DIFF(priv->xmitSeq, priv->recvAck)
>= a->xmitWin) {
priv->stats.xmitDrops++;
NG_FREE_M(m);
NG_FREE_ITEM(item);
return (ENOBUFS);
/* Check if windowing is enabled */
if (priv->conf.enableWindowing) {
/* Is our transmit window full? */
if ((u_int32_t)PPTP_SEQ_DIFF(priv->xmitSeq,
priv->recvAck) >= a->xmitWin) {
priv->stats.xmitDrops++;
NG_FREE_M(m);
NG_FREE_ITEM(item);
return (ENOBUFS);
}
}
/* Sanity check frame length */
@ -505,8 +508,10 @@ ng_pptpgre_xmit(node_p node, item_p item)
/* Include sequence number if packet contains any data */
if (m != NULL) {
gre->hasSeq = 1;
a->timeSent[priv->xmitSeq - priv->recvAck]
= ng_pptpgre_time(node);
if (priv->conf.enableWindowing) {
a->timeSent[priv->xmitSeq - priv->recvAck]
= ng_pptpgre_time(node);
}
priv->xmitSeq++;
gre->data[0] = htonl(priv->xmitSeq);
}
@ -656,33 +661,36 @@ ng_pptpgre_recv(node_p node, item_p item)
priv->recvAck = ack;
/* Update adaptive timeout stuff */
sample = ng_pptpgre_time(node) - a->timeSent[index];
diff = sample - a->rtt;
a->rtt += PPTP_ACK_ALPHA(diff);
if (diff < 0)
diff = -diff;
a->dev += PPTP_ACK_BETA(diff - a->dev);
a->ato = a->rtt + PPTP_ACK_CHI(a->dev);
if (a->ato > PPTP_MAX_TIMEOUT)
a->ato = PPTP_MAX_TIMEOUT;
if (a->ato < PPTP_MIN_TIMEOUT)
a->ato = PPTP_MIN_TIMEOUT;
if (priv->conf.enableWindowing) {
sample = ng_pptpgre_time(node) - a->timeSent[index];
diff = sample - a->rtt;
a->rtt += PPTP_ACK_ALPHA(diff);
if (diff < 0)
diff = -diff;
a->dev += PPTP_ACK_BETA(diff - a->dev);
a->ato = a->rtt + PPTP_ACK_CHI(a->dev);
if (a->ato > PPTP_MAX_TIMEOUT)
a->ato = PPTP_MAX_TIMEOUT;
if (a->ato < PPTP_MIN_TIMEOUT)
a->ato = PPTP_MIN_TIMEOUT;
/* Shift packet transmit times in our transmit window */
bcopy(a->timeSent + index + 1, a->timeSent,
sizeof(*a->timeSent) * (PPTP_XMIT_WIN - (index + 1)));
/* Shift packet transmit times in our transmit window */
bcopy(a->timeSent + index + 1, a->timeSent,
sizeof(*a->timeSent)
* (PPTP_XMIT_WIN - (index + 1)));
/* If we sent an entire window, increase window size by one */
if (PPTP_SEQ_DIFF(ack, a->winAck) >= 0
&& a->xmitWin < PPTP_XMIT_WIN) {
a->xmitWin++;
a->winAck = ack + a->xmitWin;
/* If we sent an entire window, increase window size */
if (PPTP_SEQ_DIFF(ack, a->winAck) >= 0
&& a->xmitWin < PPTP_XMIT_WIN) {
a->xmitWin++;
a->winAck = ack + a->xmitWin;
}
/* Stop/(re)start receive ACK timer as necessary */
ng_pptpgre_stop_recv_ack_timer(node);
if (priv->recvAck != priv->xmitSeq)
ng_pptpgre_start_recv_ack_timer(node);
}
/* Stop/(re)start receive ACK timer as necessary */
ng_pptpgre_stop_recv_ack_timer(node);
if (priv->recvAck != priv->xmitSeq)
ng_pptpgre_start_recv_ack_timer(node);
}
badAck:
@ -752,6 +760,9 @@ ng_pptpgre_start_recv_ack_timer(node_p node)
struct ng_pptpgre_ackp *const a = &priv->ackp;
int remain, ticks;
if (!priv->conf.enableWindowing)
return;
/* Compute how long until oldest unack'd packet times out,
and reset the timer to that time. */
KASSERT(a->rackTimerPtr == NULL, ("%s: rackTimer", __func__));
@ -788,6 +799,9 @@ ng_pptpgre_stop_recv_ack_timer(node_p node)
const priv_p priv = NG_NODE_PRIVATE(node);
struct ng_pptpgre_ackp *const a = &priv->ackp;
if (!priv->conf.enableWindowing)
return;
if (callout_stop(&a->rackTimer)) {
FREE(a->rackTimerPtr, M_NETGRAPH);
priv->timers--;

View File

@ -45,7 +45,7 @@
/* Node type name and magic cookie */
#define NG_PPTPGRE_NODE_TYPE "pptpgre"
#define NGM_PPTPGRE_COOKIE 942783547
#define NGM_PPTPGRE_COOKIE 1082548365
/* Hook names */
#define NG_PPTPGRE_HOOK_UPPER "upper" /* to upper layers */
@ -56,6 +56,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_char enableWindowing;/* enable windowing algorithm */
u_int16_t cid; /* my call id */
u_int16_t peerCid; /* peer call id */
u_int16_t recvWin; /* peer recv window size */
@ -68,6 +69,7 @@ struct ng_pptpgre_conf {
{ "enabled", &ng_parse_uint8_type }, \
{ "enableDelayedAck", &ng_parse_uint8_type }, \
{ "enableAlwaysAck", &ng_parse_uint8_type }, \
{ "enableWindowing", &ng_parse_uint8_type }, \
{ "cid", &ng_parse_hint16_type }, \
{ "peerCid", &ng_parse_hint16_type }, \
{ "recvWin", &ng_parse_uint16_type }, \