(icmp6_rip6_input) if the received data is small enough but in an

mbuf cluster, copy the data to a separate mbuf that do not use a
cluster.  this change will reduce the possiblity of packet loss
in the socket layer.

Obtained from:	KAME
This commit is contained in:
ume 2003-10-31 16:21:26 +00:00
parent 5b1d3ee076
commit 1b705657ea

View File

@ -1941,8 +1941,36 @@ icmp6_rip6_input(mp, off)
in6p->in6p_icmp6filt))
continue;
if (last) {
struct mbuf *n;
if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
struct mbuf *n = NULL;
/*
* Recent network drivers tend to allocate a single
* mbuf cluster, rather than to make a couple of
* mbufs without clusters. Also, since the IPv6 code
* path tries to avoid m_pullup(), it is highly
* probable that we still have an mbuf cluster here
* even though the necessary length can be stored in an
* mbuf's internal buffer.
* Meanwhile, the default size of the receive socket
* buffer for raw sockets is not so large. This means
* the possibility of packet loss is relatively higher
* than before. To avoid this scenario, we copy the
* received data to a separate mbuf that does not use
* a cluster, if possible.
* XXX: it is better to copy the data after stripping
* intermediate headers.
*/
if ((m->m_flags & M_EXT) && m->m_next == NULL &&
m->m_len <= MHLEN) {
MGET(n, M_DONTWAIT, m->m_type);
if (n != NULL) {
m_dup_pkthdr(n, m, M_NOWAIT);
bcopy(m->m_data, n->m_data, m->m_len);
n->m_len = m->m_len;
}
}
if (n != NULL ||
(n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
if (last->in6p_flags & IN6P_CONTROLOPTS)
ip6_savecontrol(last, n, &opts);
/* strip intermediate headers */
@ -1967,6 +1995,22 @@ icmp6_rip6_input(mp, off)
ip6_savecontrol(last, m, &opts);
/* strip intermediate headers */
m_adj(m, off);
/* avoid using mbuf clusters if possible (see above) */
if ((m->m_flags & M_EXT) && m->m_next == NULL &&
m->m_len <= MHLEN) {
struct mbuf *n;
MGET(n, M_DONTWAIT, m->m_type);
if (n != NULL) {
m_dup_pkthdr(n, m, M_NOWAIT);
bcopy(m->m_data, n->m_data, m->m_len);
n->m_len = m->m_len;
m_freem(m);
m = n;
}
}
if (sbappendaddr(&last->in6p_socket->so_rcv,
(struct sockaddr *)&fromsa, m, opts) == 0) {
m_freem(m);