Index: net/if_loop.c =================================================================== --- net/if_loop.c (revision 189854) +++ net/if_loop.c (working copy) @@ -138,6 +138,8 @@ ifp->if_ioctl = loioctl; ifp->if_output = looutput; ifp->if_snd.ifq_maxlen = ifqmaxlen; + ifp->if_hwassist = ifp->if_capabilities = ifp->if_capenable = + IFCAP_HWCSUM; if_attach(ifp); bpfattach(ifp, DLT_NULL, sizeof(u_int32_t)); if (V_loif == NULL) @@ -213,6 +215,13 @@ switch (dst->sa_family) { case AF_INET: case AF_INET6: + if (ifp->if_capenable & IFCAP_RXCSUM) { + m->m_pkthdr.csum_data = 0xffff; + m->m_pkthdr.csum_flags = CSUM_DATA_VALID | + CSUM_PSEUDO_HDR | CSUM_IP_CHECKED | + CSUM_IP_VALID; + } + m->m_pkthdr.csum_flags &= ~(CSUM_IP | CSUM_TCP | CSUM_UDP); case AF_IPX: case AF_APPLETALK: break; @@ -348,7 +357,7 @@ { struct ifaddr *ifa; struct ifreq *ifr = (struct ifreq *)data; - int error = 0; + int error = 0, mask; switch (cmd) { case SIOCSIFADDR: @@ -391,6 +400,18 @@ case SIOCSIFFLAGS: break; + case SIOCSIFCAP: + mask = ifp->if_capenable ^ ifr->ifr_reqcap; + if ((mask & IFCAP_RXCSUM) != 0) + ifp->if_capenable ^= IFCAP_RXCSUM; + if ((mask & IFCAP_TXCSUM) != 0) + ifp->if_capenable ^= IFCAP_TXCSUM; + if (ifp->if_capenable & IFCAP_TXCSUM) + ifp->if_hwassist = CSUM_IP | CSUM_TCP | CSUM_UDP; + else + ifp->if_hwassist = 0; + break; + default: error = EINVAL; }