Jan Klemkow: > > > - I turned the KASSERTS to returns. > > > - Check if the mbuf is large enough for an ether header. > > > - additionally #ifdef'd INET6 around the ip6_hdr in the new struct > > > > For non-initial fragments of TCP/UDP packets, ether_extract_headers() > > will create ext.tcp/ext.udp pointers that do not point to a protocol > > header. Should there be a check to exclude fragments? > > yes. bluhm also suggested this solution to me.
ok naddy@ For ix(4), this has been running fine for the last six hours on the ports build cluster's NFS server while package builds are ongoing. I also switched over em(4) to this and have successfully used it for a full 30-hour package build on the four amd64 ports machines with their I350 interfaces. Additionally, I've done some IPv6 testing at home over an I210. diff f8646d27d4041e5f595c04e17a876f12600deea7 f3f95d0cc0957a2f1e961cace4c3c9dd869e8c9e commit - f8646d27d4041e5f595c04e17a876f12600deea7 commit + f3f95d0cc0957a2f1e961cace4c3c9dd869e8c9e blob - c840377f0a3f1ef3c3e3072657698d8085ffd3a0 blob + 523ed5b0a18718c50bb30e2995d293fa1d2199a6 --- sys/dev/pci/if_em.c +++ sys/dev/pci/if_em.c @@ -2398,12 +2398,11 @@ em_tx_ctx_setup(struct em_queue *que, struct mbuf *mp, em_tx_ctx_setup(struct em_queue *que, struct mbuf *mp, u_int head, u_int32_t *olinfo_status, u_int32_t *cmd_type_len) { + struct ether_extracted ext; struct e1000_adv_tx_context_desc *TD; - struct ether_header *eh = mtod(mp, struct ether_header *); - struct mbuf *m; uint32_t vlan_macip_lens = 0, type_tucmd_mlhl = 0, mss_l4len_idx = 0; - int off = 0, hoff; - uint8_t ipproto, iphlen; + int off = 0; + uint8_t iphlen; *olinfo_status = 0; *cmd_type_len = 0; @@ -2418,44 +2417,26 @@ em_tx_ctx_setup(struct em_queue *que, struct mbuf *mp, } #endif - vlan_macip_lens |= (sizeof(*eh) << E1000_ADVTXD_MACLEN_SHIFT); - - switch (ntohs(eh->ether_type)) { - case ETHERTYPE_IP: { - struct ip *ip; + ether_extract_headers(mp, &ext); - m = m_getptr(mp, sizeof(*eh), &hoff); - ip = (struct ip *)(mtod(m, caddr_t) + hoff); + vlan_macip_lens |= (sizeof(*ext.eh) << E1000_ADVTXD_MACLEN_SHIFT); - iphlen = ip->ip_hl << 2; - ipproto = ip->ip_p; + if (ext.ip4) { + iphlen = ext.ip4->ip_hl << 2; type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_IPV4; if (ISSET(mp->m_pkthdr.csum_flags, M_IPV4_CSUM_OUT)) { *olinfo_status |= E1000_TXD_POPTS_IXSM << 8; off = 1; } - - break; - } #ifdef INET6 - case ETHERTYPE_IPV6: { - struct ip6_hdr *ip6; + } else if (ext.ip6) { + iphlen = sizeof(*ext.ip6); - m = m_getptr(mp, sizeof(*eh), &hoff); - ip6 = (struct ip6_hdr *)(mtod(m, caddr_t) + hoff); - - iphlen = sizeof(*ip6); - ipproto = ip6->ip6_nxt; - type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_IPV6; - break; - } #endif - default: + } else { iphlen = 0; - ipproto = 0; - break; } *cmd_type_len |= E1000_ADVTXD_DTYP_DATA | E1000_ADVTXD_DCMD_IFCS; @@ -2464,21 +2445,18 @@ em_tx_ctx_setup(struct em_queue *que, struct mbuf *mp, vlan_macip_lens |= iphlen; type_tucmd_mlhl |= E1000_ADVTXD_DCMD_DEXT | E1000_ADVTXD_DTYP_CTXT; - switch (ipproto) { - case IPPROTO_TCP: + if (ext.tcp) { type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_L4T_TCP; if (ISSET(mp->m_pkthdr.csum_flags, M_TCP_CSUM_OUT)) { *olinfo_status |= E1000_TXD_POPTS_TXSM << 8; off = 1; } - break; - case IPPROTO_UDP: + } else if (ext.udp) { type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_L4T_UDP; if (ISSET(mp->m_pkthdr.csum_flags, M_UDP_CSUM_OUT)) { *olinfo_status |= E1000_TXD_POPTS_TXSM << 8; off = 1; } - break; } if (!off) -- Christian "naddy" Weisgerber na...@mips.inka.de