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:
mav 2009-01-18 19:25:36 +00:00
parent 963ae12224
commit 74ed22786b
3 changed files with 80 additions and 49 deletions

View File

@ -459,6 +459,13 @@ ng_deflate_compress(node_p node, struct mbuf *m, struct mbuf **resultp)
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. */
m_copydata(m, 0, inlen, (caddr_t)priv->inbuf);
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.OutOctets+=inlen;
} else {
NG_FREE_M(m);
/* Install header. */
((u_int16_t *)priv->outbuf)[0] = htons(PROT_COMPD);
((u_int16_t *)priv->outbuf)[1] = htons(priv->seqnum);
/* Return packet in an mbuf. */
*resultp = m_devget((caddr_t)priv->outbuf, outlen, 0, NULL,
NULL);
if (*resultp == NULL) {
m_copyback(m, 0, outlen, (caddr_t)priv->outbuf);
if (m->m_pkthdr.len < outlen) {
m_freem(m);
priv->stats.Errors++;
return (ENOMEM);
};
} else if (outlen < m->m_pkthdr.len)
m_adj(m, outlen - m->m_pkthdr.len);
*resultp = m;
priv->stats.FramesComp++;
priv->stats.OutOctets+=outlen;
}
@ -546,6 +553,13 @@ ng_deflate_decompress(node_p node, struct mbuf *m, struct mbuf **resultp)
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. */
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. */
outlen -= priv->cx.avail_out;
NG_FREE_M(m);
/* Decompress protocol. */
if ((priv->outbuf[1] & 0x01) != 0) {
priv->outbuf[0] = 0;
/* Return packet in an mbuf. */
*resultp = m_devget((caddr_t)priv->outbuf, outlen, 0,
NULL, NULL);
m_copyback(m, 0, outlen, (caddr_t)priv->outbuf);
} else {
outlen--;
/* Return packet in an mbuf. */
*resultp = m_devget((caddr_t)(priv->outbuf + 1),
outlen, 0, NULL, NULL);
m_copyback(m, 0, outlen, (caddr_t)(priv->outbuf + 1));
}
if (*resultp == NULL) {
if (m->m_pkthdr.len < outlen) {
m_freem(m);
priv->stats.Errors++;
priv->seqnum = 0;
return (ENOMEM);
};
} else if (outlen < m->m_pkthdr.len)
m_adj(m, outlen - m->m_pkthdr.len);
*resultp = m;
priv->stats.FramesPlain++;
priv->stats.OutOctets+=outlen;

View File

@ -470,6 +470,11 @@ ng_mppc_compress(node_p node, struct mbuf **datap)
u_int16_t header;
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 */
header = d->cc;
@ -529,8 +534,12 @@ err1:
header |= MPPC_FLAG_RESTART;
/* Replace m by the compresed one. */
m_freem(m);
m = m_devget((caddr_t)outbuf, outlen, 0, NULL, NULL);
m_copyback(m, 0, outlen, (caddr_t)outbuf);
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
|| (flags & MPPC_SAVE_HISTORY) == 0;
@ -538,7 +547,7 @@ err1:
free(inbuf, M_NETGRAPH_MPPC);
free(outbuf, M_NETGRAPH_MPPC);
/* Check m_devget() result. */
/* Check mbuf chain reload result. */
if (m == NULL) {
if (!d->flushed) {
MPPC_InitCompressionHistory(d->history);
@ -557,18 +566,6 @@ err1:
/* Set header bits */
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 */
if ((d->cfg.bits & MPPE_STATELESS) != 0
|| (d->cc & MPPE_UPDATE_MASK) == MPPE_UPDATE_FLAG) {
@ -615,6 +612,11 @@ ng_mppc_decompress(node_p node, struct mbuf **datap)
u_int numLost;
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 */
if (m->m_pkthdr.len < MPPC_HDRLEN) {
m_freem(m);
@ -694,11 +696,6 @@ ng_mppc_decompress(node_p node, struct mbuf **datap)
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 */
m1 = m;
while (m1 != NULL) {
@ -786,8 +783,12 @@ failed:
free(buf, M_NETGRAPH_MPPC);
len = decomplen - destCnt;
m_freem(m);
m = m_devget((caddr_t)decompbuf, len, 0, NULL, NULL);
m_copyback(m, 0, len, (caddr_t)decompbuf);
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);
}
#endif

View File

@ -400,11 +400,16 @@ ng_pred1_compress(node_p node, struct mbuf *m, struct mbuf **resultp)
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. */
m_copydata(m, 0, inlen, (caddr_t)(priv->inbuf + 2));
NG_FREE_M(m);
lenn = htons(inlen & 0x7FFF);
/* Compute FCS. */
@ -437,12 +442,14 @@ ng_pred1_compress(node_p node, struct mbuf *m, struct mbuf **resultp)
outlen += 2;
/* Return packet in an mbuf. */
*resultp = m_devget((caddr_t)out, outlen, 0, NULL, NULL);
if (*resultp == NULL) {
priv->stats.Errors++;
return (ENOMEM);
};
m_copyback(m, 0, outlen, (caddr_t)out);
if (m->m_pkthdr.len < outlen) {
m_freem(m);
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;
return (0);
@ -471,6 +478,13 @@ ng_pred1_decompress(node_p node, struct mbuf *m, struct mbuf **resultp)
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. */
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? */
if (cf) {
NG_FREE_M(m);
priv->stats.FramesComp++;
len1 = Pred1Decompress(node, priv->inbuf + 2, priv->outbuf,
inlen - 4, PRED1_BUF_SIZE);
if (len != len1) {
/* Error is detected. Send reset request */
m_freem(m);
priv->stats.Errors++;
log(LOG_NOTICE, "ng_pred1: Comp length error (%d) "
"--> 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);
if (fcs != PPP_GOODFCS) {
m_freem(m);
priv->stats.Errors++;
log(LOG_NOTICE, "ng_pred1: Pred1: Bad CRC-16\n");
return (EIO);
}
/* Return packet in an mbuf. */
*resultp = m_devget((caddr_t)priv->outbuf, len, 0, NULL, NULL);
if (*resultp == NULL) {
m_copyback(m, 0, len, (caddr_t)priv->outbuf);
if (m->m_pkthdr.len < len) {
m_freem(m);
priv->stats.Errors++;
return (ENOMEM);
};
} else if (len < m->m_pkthdr.len)
m_adj(m, len - m->m_pkthdr.len);
*resultp = m;
} else {
priv->stats.FramesUncomp++;