MFp4 bz_ipv6_fast:

Add TSO6 and LRO/IPv6 support.
  Fix the module Makefile to at least properly inlcude opt_inet6.h
  and allow builds without INET or INET6.

  Sponsored by:	The FreeBSD Foundation
  Sponsored by:	iXsystems

Reviewed by:	gnn (as part of the whole)
MFC After:	3 days
This commit is contained in:
Bjoern A. Zeeb 2012-05-25 03:02:56 +00:00
parent 47cfa99a50
commit e2c0161e2e
2 changed files with 80 additions and 29 deletions

View file

@ -162,7 +162,7 @@ static void ixgbe_dma_free(struct adapter *, struct ixgbe_dma_alloc *);
static void ixgbe_add_rx_process_limit(struct adapter *, const char *,
const char *, int *, int);
static bool ixgbe_tx_ctx_setup(struct tx_ring *, struct mbuf *);
static bool ixgbe_tso_setup(struct tx_ring *, struct mbuf *, u32 *);
static bool ixgbe_tso_setup(struct tx_ring *, struct mbuf *, u32 *, u32 *);
static void ixgbe_set_ivar(struct adapter *, u8, u8, s8);
static void ixgbe_configure_ivars(struct adapter *);
static u8 * ixgbe_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *);
@ -997,6 +997,8 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
ifp->if_capenable ^= IFCAP_HWCSUM;
if (mask & IFCAP_TSO4)
ifp->if_capenable ^= IFCAP_TSO4;
if (mask & IFCAP_TSO6)
ifp->if_capenable ^= IFCAP_TSO6;
if (mask & IFCAP_LRO)
ifp->if_capenable ^= IFCAP_LRO;
if (mask & IFCAP_VLAN_HWTAGGING)
@ -1061,7 +1063,7 @@ ixgbe_init_locked(struct adapter *adapter)
/* Set the various hardware offload abilities */
ifp->if_hwassist = 0;
if (ifp->if_capenable & IFCAP_TSO4)
if (ifp->if_capenable & IFCAP_TSO)
ifp->if_hwassist |= CSUM_TSO;
if (ifp->if_capenable & IFCAP_TXCSUM) {
ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP);
@ -1767,9 +1769,8 @@ ixgbe_xmit(struct tx_ring *txr, struct mbuf **m_headp)
** a packet.
*/
if (m_head->m_pkthdr.csum_flags & CSUM_TSO) {
if (ixgbe_tso_setup(txr, m_head, &paylen)) {
if (ixgbe_tso_setup(txr, m_head, &paylen, &olinfo_status)) {
cmd_type_len |= IXGBE_ADVTXD_DCMD_TSE;
olinfo_status |= IXGBE_TXD_POPTS_IXSM << 8;
olinfo_status |= IXGBE_TXD_POPTS_TXSM << 8;
olinfo_status |= paylen << IXGBE_ADVTXD_PAYLEN_SHIFT;
++adapter->tso_tx;
@ -2562,7 +2563,7 @@ ixgbe_setup_interface(device_t dev, struct adapter *adapter)
*/
ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_TSO4 | IFCAP_VLAN_HWCSUM;
ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_TSO | IFCAP_VLAN_HWCSUM;
ifp->if_capabilities |= IFCAP_JUMBO_MTU;
ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING
| IFCAP_VLAN_HWTSO
@ -3234,6 +3235,7 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp)
case ETHERTYPE_IPV6:
ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
ip_hlen = sizeof(struct ip6_hdr);
/* XXX-BZ this will go badly in case of ext hdrs. */
ipproto = ip6->ip6_nxt;
type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV6;
break;
@ -3292,17 +3294,23 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp)
*
**********************************************************************/
static bool
ixgbe_tso_setup(struct tx_ring *txr, struct mbuf *mp, u32 *paylen)
ixgbe_tso_setup(struct tx_ring *txr, struct mbuf *mp, u32 *paylen,
u32 *olinfo_status)
{
struct adapter *adapter = txr->adapter;
struct ixgbe_adv_tx_context_desc *TXD;
struct ixgbe_tx_buf *tx_buffer;
u32 vlan_macip_lens = 0, type_tucmd_mlhl = 0;
u32 mss_l4len_idx = 0;
u16 vtag = 0;
int ctxd, ehdrlen, hdrlen, ip_hlen, tcp_hlen;
u32 mss_l4len_idx = 0, len;
u16 vtag = 0, eh_type;
int ctxd, ehdrlen, ip_hlen, tcp_hlen;
struct ether_vlan_header *eh;
#ifdef INET6
struct ip6_hdr *ip6;
#endif
#ifdef INET
struct ip *ip;
#endif
struct tcphdr *th;
@ -3311,32 +3319,62 @@ ixgbe_tso_setup(struct tx_ring *txr, struct mbuf *mp, u32 *paylen)
* Jump over vlan headers if already present
*/
eh = mtod(mp, struct ether_vlan_header *);
if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN))
if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
else
eh_type = eh->evl_proto;
} else {
ehdrlen = ETHER_HDR_LEN;
eh_type = eh->evl_encap_proto;
}
/* Ensure we have at least the IP+TCP header in the first mbuf. */
if (mp->m_len < ehdrlen + sizeof(struct ip) + sizeof(struct tcphdr))
return FALSE;
len = ehdrlen + sizeof(struct tcphdr);
switch (ntohs(eh_type)) {
#ifdef INET6
case ETHERTYPE_IPV6:
if (mp->m_len < len + sizeof(struct ip6_hdr))
return FALSE;
ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
/* XXX-BZ For now we do not pretend to support ext. hdrs. */
if (ip6->ip6_nxt != IPPROTO_TCP)
return FALSE;
ip_hlen = sizeof(struct ip6_hdr);
th = (struct tcphdr *)((caddr_t)ip6 + ip_hlen);
th->th_sum = in6_cksum_pseudo(ip6, 0, IPPROTO_TCP, 0);
type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV6;
break;
#endif
#ifdef INET
case ETHERTYPE_IP:
if (mp->m_len < len + sizeof(struct ip))
return FALSE;
ip = (struct ip *)(mp->m_data + ehdrlen);
if (ip->ip_p != IPPROTO_TCP)
return FALSE;
ip->ip_sum = 0;
ip_hlen = ip->ip_hl << 2;
th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
th->th_sum = in_pseudo(ip->ip_src.s_addr,
ip->ip_dst.s_addr, htons(IPPROTO_TCP));
type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;
/* Tell transmit desc to also do IPv4 checksum. */
*olinfo_status |= IXGBE_TXD_POPTS_IXSM << 8;
break;
#endif
default:
panic("%s: CSUM_TSO but no supported IP version (0x%04x)",
__func__, ntohs(eh_type));
break;
}
ctxd = txr->next_avail_desc;
tx_buffer = &txr->tx_buffers[ctxd];
TXD = (struct ixgbe_adv_tx_context_desc *) &txr->tx_base[ctxd];
ip = (struct ip *)(mp->m_data + ehdrlen);
if (ip->ip_p != IPPROTO_TCP)
return FALSE; /* 0 */
ip->ip_sum = 0;
ip_hlen = ip->ip_hl << 2;
th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
th->th_sum = in_pseudo(ip->ip_src.s_addr,
ip->ip_dst.s_addr, htons(IPPROTO_TCP));
tcp_hlen = th->th_off << 2;
hdrlen = ehdrlen + ip_hlen + tcp_hlen;
/* This is used in the transmit desc in encap */
*paylen = mp->m_pkthdr.len - hdrlen;
*paylen = mp->m_pkthdr.len - ehdrlen - ip_hlen - tcp_hlen;
/* VLAN MACLEN IPLEN */
if (mp->m_flags & M_VLANTAG) {
@ -3351,10 +3389,8 @@ ixgbe_tso_setup(struct tx_ring *txr, struct mbuf *mp, u32 *paylen)
/* ADV DTYPE TUCMD */
type_tucmd_mlhl |= IXGBE_ADVTXD_DCMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT;
type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;
TXD->type_tucmd_mlhl |= htole32(type_tucmd_mlhl);
/* MSS L4LEN IDX */
mss_l4len_idx |= (mp->m_pkthdr.tso_segsz << IXGBE_ADVTXD_MSS_SHIFT);
mss_l4len_idx |= (tcp_hlen << IXGBE_ADVTXD_L4LEN_SHIFT);
@ -4295,15 +4331,17 @@ ixgbe_rx_input(struct rx_ring *rxr, struct ifnet *ifp, struct mbuf *m, u32 ptype
{
/*
* ATM LRO is only for IPv4/TCP packets and TCP checksum of the packet
* ATM LRO is only for IP/TCP packets and TCP checksum of the packet
* should be computed by hardware. Also it should not have VLAN tag in
* ethernet header.
* ethernet header. In case of IPv6 we do not yet support ext. hdrs.
*/
if (rxr->lro_enabled &&
(ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0 &&
(ptype & IXGBE_RXDADV_PKTTYPE_ETQF) == 0 &&
(ptype & (IXGBE_RXDADV_PKTTYPE_IPV4 | IXGBE_RXDADV_PKTTYPE_TCP)) ==
(IXGBE_RXDADV_PKTTYPE_IPV4 | IXGBE_RXDADV_PKTTYPE_TCP) &&
((ptype & (IXGBE_RXDADV_PKTTYPE_IPV4 | IXGBE_RXDADV_PKTTYPE_TCP)) ==
(IXGBE_RXDADV_PKTTYPE_IPV4 | IXGBE_RXDADV_PKTTYPE_TCP) ||
(ptype & (IXGBE_RXDADV_PKTTYPE_IPV6 | IXGBE_RXDADV_PKTTYPE_TCP)) ==
(IXGBE_RXDADV_PKTTYPE_IPV6 | IXGBE_RXDADV_PKTTYPE_TCP)) &&
(m->m_pkthdr.csum_flags & (CSUM_DATA_VALID | CSUM_PSEUDO_HDR)) ==
(CSUM_DATA_VALID | CSUM_PSEUDO_HDR)) {
/*

View file

@ -2,10 +2,23 @@
.PATH: ${.CURDIR}/../../dev/ixgbe
KMOD = ixgbe
SRCS = device_if.h bus_if.h pci_if.h
SRCS += opt_inet.h opt_inet6.h
SRCS += ixgbe.c ixv.c
# Shared source
SRCS += ixgbe_common.c ixgbe_api.c ixgbe_phy.c ixgbe_mbx.c ixgbe_vf.c
SRCS += ixgbe_82599.c ixgbe_82598.c ixgbe_x540.c
CFLAGS+= -I${.CURDIR}/../../dev/ixgbe -DSMP -DIXGBE_FDIR
.if !defined(KERNBUILDDIR)
.if ${MK_INET_SUPPORT} != "no"
opt_inet.h:
@echo "#define INET 1" > ${.TARGET}
.endif
.if ${MK_INET6_SUPPORT} != "no"
opt_inet6.h:
@echo "#define INET6 1" > ${.TARGET}
.endif
.endif
.include <bsd.kmod.mk>