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 [email protected]