Use m_unshare()+m_copyback() instead of m_freem()+m_devget() to keep

original mbuf chain headers. It can be less efficient in some cases, but it
looks better then mess of copying headers into the nonempty chain.
This commit is contained in:
Alexander Motin 2009-01-18 19:25:36 +00:00
parent b51ba332bb
commit e4651e0595
3 changed files with 80 additions and 49 deletions

@ -459,6 +459,13 @@ ng_deflate_compress(node_p node, struct mbuf *m, struct mbuf **resultp)
return (ENOMEM); return (ENOMEM);
} }
/* We must own the mbuf chain exclusively to modify it. */
m = m_unshare(m, M_DONTWAIT);
if (m == NULL) {
priv->stats.Errors++;
return (ENOMEM);
}
/* Work with contiguous regions of memory. */ /* Work with contiguous regions of memory. */
m_copydata(m, 0, inlen, (caddr_t)priv->inbuf); m_copydata(m, 0, inlen, (caddr_t)priv->inbuf);
outlen = DEFLATE_BUF_SIZE; outlen = DEFLATE_BUF_SIZE;
@ -497,19 +504,19 @@ ng_deflate_compress(node_p node, struct mbuf *m, struct mbuf **resultp)
priv->stats.FramesUncomp++; priv->stats.FramesUncomp++;
priv->stats.OutOctets+=inlen; priv->stats.OutOctets+=inlen;
} else { } else {
NG_FREE_M(m);
/* Install header. */ /* Install header. */
((u_int16_t *)priv->outbuf)[0] = htons(PROT_COMPD); ((u_int16_t *)priv->outbuf)[0] = htons(PROT_COMPD);
((u_int16_t *)priv->outbuf)[1] = htons(priv->seqnum); ((u_int16_t *)priv->outbuf)[1] = htons(priv->seqnum);
/* Return packet in an mbuf. */ /* Return packet in an mbuf. */
*resultp = m_devget((caddr_t)priv->outbuf, outlen, 0, NULL, m_copyback(m, 0, outlen, (caddr_t)priv->outbuf);
NULL); if (m->m_pkthdr.len < outlen) {
if (*resultp == NULL) { m_freem(m);
priv->stats.Errors++; priv->stats.Errors++;
return (ENOMEM); return (ENOMEM);
}; } else if (outlen < m->m_pkthdr.len)
m_adj(m, outlen - m->m_pkthdr.len);
*resultp = m;
priv->stats.FramesComp++; priv->stats.FramesComp++;
priv->stats.OutOctets+=outlen; priv->stats.OutOctets+=outlen;
} }
@ -546,6 +553,13 @@ ng_deflate_decompress(node_p node, struct mbuf *m, struct mbuf **resultp)
return (ENOMEM); return (ENOMEM);
} }
/* We must own the mbuf chain exclusively to modify it. */
m = m_unshare(m, M_DONTWAIT);
if (m == NULL) {
priv->stats.Errors++;
return (ENOMEM);
}
/* Work with contiguous regions of memory. */ /* Work with contiguous regions of memory. */
m_copydata(m, 0, inlen, (caddr_t)priv->inbuf); m_copydata(m, 0, inlen, (caddr_t)priv->inbuf);
@ -610,25 +624,24 @@ ng_deflate_decompress(node_p node, struct mbuf *m, struct mbuf **resultp)
/* Calculate resulting size. */ /* Calculate resulting size. */
outlen -= priv->cx.avail_out; outlen -= priv->cx.avail_out;
NG_FREE_M(m);
/* Decompress protocol. */ /* Decompress protocol. */
if ((priv->outbuf[1] & 0x01) != 0) { if ((priv->outbuf[1] & 0x01) != 0) {
priv->outbuf[0] = 0; priv->outbuf[0] = 0;
/* Return packet in an mbuf. */ /* Return packet in an mbuf. */
*resultp = m_devget((caddr_t)priv->outbuf, outlen, 0, m_copyback(m, 0, outlen, (caddr_t)priv->outbuf);
NULL, NULL);
} else { } else {
outlen--; outlen--;
/* Return packet in an mbuf. */ /* Return packet in an mbuf. */
*resultp = m_devget((caddr_t)(priv->outbuf + 1), m_copyback(m, 0, outlen, (caddr_t)(priv->outbuf + 1));
outlen, 0, NULL, NULL);
} }
if (*resultp == NULL) { if (m->m_pkthdr.len < outlen) {
m_freem(m);
priv->stats.Errors++; priv->stats.Errors++;
priv->seqnum = 0; priv->seqnum = 0;
return (ENOMEM); return (ENOMEM);
}; } else if (outlen < m->m_pkthdr.len)
m_adj(m, outlen - m->m_pkthdr.len);
*resultp = m;
priv->stats.FramesPlain++; priv->stats.FramesPlain++;
priv->stats.OutOctets+=outlen; priv->stats.OutOctets+=outlen;

@ -470,6 +470,11 @@ ng_mppc_compress(node_p node, struct mbuf **datap)
u_int16_t header; u_int16_t header;
struct mbuf *m = *datap; struct mbuf *m = *datap;
/* We must own the mbuf chain exclusively to modify it. */
m = m_unshare(m, M_DONTWAIT);
if (m == NULL)
return (ENOMEM);
/* Initialize */ /* Initialize */
header = d->cc; header = d->cc;
@ -529,8 +534,12 @@ err1:
header |= MPPC_FLAG_RESTART; header |= MPPC_FLAG_RESTART;
/* Replace m by the compresed one. */ /* Replace m by the compresed one. */
m_freem(m); m_copyback(m, 0, outlen, (caddr_t)outbuf);
m = m_devget((caddr_t)outbuf, outlen, 0, NULL, NULL); if (m->m_pkthdr.len < outlen) {
m_freem(m);
m = NULL;
} else if (outlen < m->m_pkthdr.len)
m_adj(m, outlen - m->m_pkthdr.len);
} }
d->flushed = (rtn & MPPC_EXPANDED) != 0 d->flushed = (rtn & MPPC_EXPANDED) != 0
|| (flags & MPPC_SAVE_HISTORY) == 0; || (flags & MPPC_SAVE_HISTORY) == 0;
@ -538,7 +547,7 @@ err1:
free(inbuf, M_NETGRAPH_MPPC); free(inbuf, M_NETGRAPH_MPPC);
free(outbuf, M_NETGRAPH_MPPC); free(outbuf, M_NETGRAPH_MPPC);
/* Check m_devget() result. */ /* Check mbuf chain reload result. */
if (m == NULL) { if (m == NULL) {
if (!d->flushed) { if (!d->flushed) {
MPPC_InitCompressionHistory(d->history); MPPC_InitCompressionHistory(d->history);
@ -557,18 +566,6 @@ err1:
/* Set header bits */ /* Set header bits */
header |= MPPC_FLAG_ENCRYPTED; header |= MPPC_FLAG_ENCRYPTED;
/* We must own the mbuf chain exclusively to modify it. */
m = m_unshare(m, M_DONTWAIT);
if (m == NULL) {
if (!d->flushed) {
#ifdef NETGRAPH_MPPC_COMPRESSION
MPPC_InitCompressionHistory(d->history);
#endif
d->flushed = 1;
}
return (ENOMEM);
}
/* Update key if it's time */ /* Update key if it's time */
if ((d->cfg.bits & MPPE_STATELESS) != 0 if ((d->cfg.bits & MPPE_STATELESS) != 0
|| (d->cc & MPPE_UPDATE_MASK) == MPPE_UPDATE_FLAG) { || (d->cc & MPPE_UPDATE_MASK) == MPPE_UPDATE_FLAG) {
@ -615,6 +612,11 @@ ng_mppc_decompress(node_p node, struct mbuf **datap)
u_int numLost; u_int numLost;
struct mbuf *m = *datap; struct mbuf *m = *datap;
/* We must own the mbuf chain exclusively to modify it. */
m = m_unshare(m, M_DONTWAIT);
if (m == NULL)
return (ENOMEM);
/* Pull off header */ /* Pull off header */
if (m->m_pkthdr.len < MPPC_HDRLEN) { if (m->m_pkthdr.len < MPPC_HDRLEN) {
m_freem(m); m_freem(m);
@ -694,11 +696,6 @@ ng_mppc_decompress(node_p node, struct mbuf **datap)
d->cfg.startkey, d->key, &d->rc4); d->cfg.startkey, d->key, &d->rc4);
} }
/* We must own the mbuf chain exclusively to modify it. */
m = m_unshare(m, M_DONTWAIT);
if (m == NULL)
return (ENOMEM);
/* Decrypt packet */ /* Decrypt packet */
m1 = m; m1 = m;
while (m1 != NULL) { while (m1 != NULL) {
@ -786,8 +783,12 @@ failed:
free(buf, M_NETGRAPH_MPPC); free(buf, M_NETGRAPH_MPPC);
len = decomplen - destCnt; len = decomplen - destCnt;
m_freem(m); m_copyback(m, 0, len, (caddr_t)decompbuf);
m = m_devget((caddr_t)decompbuf, len, 0, NULL, NULL); if (m->m_pkthdr.len < len) {
m_freem(m);
m = NULL;
} else if (len < m->m_pkthdr.len)
m_adj(m, len - m->m_pkthdr.len);
free(decompbuf, M_NETGRAPH_MPPC); free(decompbuf, M_NETGRAPH_MPPC);
} }
#endif #endif

@ -400,11 +400,16 @@ ng_pred1_compress(node_p node, struct mbuf *m, struct mbuf **resultp)
return (ENOMEM); return (ENOMEM);
} }
/* We must own the mbuf chain exclusively to modify it. */
m = m_unshare(m, M_DONTWAIT);
if (m == NULL) {
priv->stats.Errors++;
return (ENOMEM);
}
/* Work with contiguous regions of memory. */ /* Work with contiguous regions of memory. */
m_copydata(m, 0, inlen, (caddr_t)(priv->inbuf + 2)); m_copydata(m, 0, inlen, (caddr_t)(priv->inbuf + 2));
NG_FREE_M(m);
lenn = htons(inlen & 0x7FFF); lenn = htons(inlen & 0x7FFF);
/* Compute FCS. */ /* Compute FCS. */
@ -437,12 +442,14 @@ ng_pred1_compress(node_p node, struct mbuf *m, struct mbuf **resultp)
outlen += 2; outlen += 2;
/* Return packet in an mbuf. */ /* Return packet in an mbuf. */
*resultp = m_devget((caddr_t)out, outlen, 0, NULL, NULL); m_copyback(m, 0, outlen, (caddr_t)out);
if (*resultp == NULL) { if (m->m_pkthdr.len < outlen) {
priv->stats.Errors++; m_freem(m);
return (ENOMEM); priv->stats.Errors++;
}; return (ENOMEM);
} else if (outlen < m->m_pkthdr.len)
m_adj(m, outlen - m->m_pkthdr.len);
*resultp = m;
priv->stats.OutOctets += outlen; priv->stats.OutOctets += outlen;
return (0); return (0);
@ -471,6 +478,13 @@ ng_pred1_decompress(node_p node, struct mbuf *m, struct mbuf **resultp)
return (ENOMEM); return (ENOMEM);
} }
/* We must own the mbuf chain exclusively to modify it. */
m = m_unshare(m, M_DONTWAIT);
if (m == NULL) {
priv->stats.Errors++;
return (ENOMEM);
}
/* Work with contiguous regions of memory. */ /* Work with contiguous regions of memory. */
m_copydata(m, 0, inlen, (caddr_t)priv->inbuf); m_copydata(m, 0, inlen, (caddr_t)priv->inbuf);
@ -485,13 +499,12 @@ ng_pred1_decompress(node_p node, struct mbuf *m, struct mbuf **resultp)
/* Is data compressed or not really? */ /* Is data compressed or not really? */
if (cf) { if (cf) {
NG_FREE_M(m);
priv->stats.FramesComp++; priv->stats.FramesComp++;
len1 = Pred1Decompress(node, priv->inbuf + 2, priv->outbuf, len1 = Pred1Decompress(node, priv->inbuf + 2, priv->outbuf,
inlen - 4, PRED1_BUF_SIZE); inlen - 4, PRED1_BUF_SIZE);
if (len != len1) { if (len != len1) {
/* Error is detected. Send reset request */ /* Error is detected. Send reset request */
m_freem(m);
priv->stats.Errors++; priv->stats.Errors++;
log(LOG_NOTICE, "ng_pred1: Comp length error (%d) " log(LOG_NOTICE, "ng_pred1: Comp length error (%d) "
"--> len (%d)\n", len, len1); "--> len (%d)\n", len, len1);
@ -510,17 +523,21 @@ ng_pred1_decompress(node_p node, struct mbuf *m, struct mbuf **resultp)
fcs = Crc16(fcs, priv->inbuf + inlen - 2, 2); fcs = Crc16(fcs, priv->inbuf + inlen - 2, 2);
if (fcs != PPP_GOODFCS) { if (fcs != PPP_GOODFCS) {
m_freem(m);
priv->stats.Errors++; priv->stats.Errors++;
log(LOG_NOTICE, "ng_pred1: Pred1: Bad CRC-16\n"); log(LOG_NOTICE, "ng_pred1: Pred1: Bad CRC-16\n");
return (EIO); return (EIO);
} }
/* Return packet in an mbuf. */ /* Return packet in an mbuf. */
*resultp = m_devget((caddr_t)priv->outbuf, len, 0, NULL, NULL); m_copyback(m, 0, len, (caddr_t)priv->outbuf);
if (*resultp == NULL) { if (m->m_pkthdr.len < len) {
m_freem(m);
priv->stats.Errors++; priv->stats.Errors++;
return (ENOMEM); return (ENOMEM);
}; } else if (len < m->m_pkthdr.len)
m_adj(m, len - m->m_pkthdr.len);
*resultp = m;
} else { } else {
priv->stats.FramesUncomp++; priv->stats.FramesUncomp++;