diff --git a/sys/arm64/broadcom/genet/if_genet.c b/sys/arm64/broadcom/genet/if_genet.c --- a/sys/arm64/broadcom/genet/if_genet.c +++ b/sys/arm64/broadcom/genet/if_genet.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -97,9 +98,27 @@ #define TX_MAX_SEGS 20 -/* Maximum number of mbufs to send to if_input */ +static SYSCTL_NODE(_hw, OID_AUTO, genet, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, + "genet driver parameters"); + +/* Maximum number of mbufs to pass per call to if_input */ static int gen_rx_batch = 16 /* RX_BATCH_DEFAULT */; -TUNABLE_INT("hw.gen.rx_batch", &gen_rx_batch); +SYSCTL_INT(_hw_genet, OID_AUTO, rx_batch, CTLFLAG_RDTUN, + &gen_rx_batch, 0, "max mbufs per call to if_input"); + +TUNABLE_INT("hw.gen.rx_batch", &gen_rx_batch); /* old name/interface */ + +/* + * Transmitting packets with only an Ethernet header in the first mbuf + * fails. Examples include reflected ICMPv6 packets, e.g. echo replies; + * forwarded IPv6/TCP packets; and forwarded IPv4/TCP packets that use NAT + * with IPFW. Pulling up the sizes of ether_header + ip6_hdr + icmp6_hdr + * seems to work for both ICMPv6 and TCP over IPv6, as well as the IPv4/TCP + * case. + */ +static int gen_tx_hdr_min = 56; /* ether_header + ip6_hdr + icmp6_hdr */ +SYSCTL_INT(_hw_genet, OID_AUTO, tx_hdr_min, CTLFLAG_RW, + &gen_tx_hdr_min, 0, "header to add to packets with ether header only"); static struct ofw_compat_data compat_data[] = { { "brcm,genet-v1", 1 }, @@ -995,31 +1014,19 @@ m = *mp; /* - * Reflected ICMPv6 packets, e.g. echo replies, tend to get laid - * out with only the Ethernet header in the first mbuf, and this - * doesn't seem to work. Forwarded TCP packets over IPv6 also - * fail if laid out with only the Ethernet header in the first mbuf. - * For now, pull up any IPv6 packet with that layout. Maybe IPv4 - * needs it but we haven't run into it. Pulling up the sizes of - * ether_header + ip6_header + icmp6_hdr seems to work for both - * ICMPv6 and TCP over IPv6. + * Don't attempt to send packets with only an Ethernet header in + * first mbuf; see comment above with gen_tx_hdr_min. */ -#define IP6_PULLUP_LEN (sizeof(struct ether_header) + \ - sizeof(struct ip6_hdr) + 8) if (m->m_len == sizeof(struct ether_header)) { - int ether_type = mtod(m, struct ether_header *)->ether_type; - if (ntohs(ether_type) == ETHERTYPE_IPV6) { - m = m_pullup(m, MIN(m->m_pkthdr.len, IP6_PULLUP_LEN)); - if (m == NULL) { - if (sc->ifp->if_flags & IFF_DEBUG) - device_printf(sc->dev, - "IPV6 pullup fail\n"); - *mp = NULL; - return (ENOMEM); - } + m = m_pullup(m, MIN(m->m_pkthdr.len, gen_tx_hdr_min)); + if (m == NULL) { + if (sc->ifp->if_flags & IFF_DEBUG) + device_printf(sc->dev, + "header pullup fail\n"); + *mp = NULL; + return (ENOMEM); } } -#undef IP6_PULLUP_LEN if ((if_getcapenable(sc->ifp) & (IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6)) != 0) {