(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:
parent
5b1d3ee076
commit
1b705657ea
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user