cxgbe(4): support for IPv6 TSO and LRO.
Submitted by: bz (this is a modified version of that patch)
This commit is contained in:
parent
8f8a2520d7
commit
a1ea9a8276
@ -392,7 +392,7 @@ struct sge_txq {
|
||||
/* stats for common events first */
|
||||
|
||||
uint64_t txcsum; /* # of times hardware assisted with checksum */
|
||||
uint64_t tso_wrs; /* # of IPv4 TSO work requests */
|
||||
uint64_t tso_wrs; /* # of TSO work requests */
|
||||
uint64_t vlan_insertion;/* # of times VLAN tag was inserted */
|
||||
uint64_t imm_wrs; /* # of work requests with immediate data */
|
||||
uint64_t sgl_wrs; /* # of work requests with direct SGL */
|
||||
@ -412,7 +412,7 @@ struct sge_rxq {
|
||||
struct sge_fl fl; /* MUST follow iq */
|
||||
|
||||
struct ifnet *ifp; /* the interface this rxq belongs to */
|
||||
#ifdef INET
|
||||
#if defined(INET) || defined(INET6)
|
||||
struct lro_ctrl lro; /* LRO state */
|
||||
#endif
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_inet6.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -29,6 +29,7 @@
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_inet6.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/conf.h>
|
||||
@ -823,7 +824,7 @@ cxgbe_probe(device_t dev)
|
||||
#define T4_CAP (IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU | IFCAP_HWCSUM | \
|
||||
IFCAP_VLAN_HWCSUM | IFCAP_TSO | IFCAP_JUMBO_MTU | IFCAP_LRO | \
|
||||
IFCAP_VLAN_HWTSO | IFCAP_HWCSUM_IPV6)
|
||||
#define T4_CAP_ENABLE (T4_CAP & ~IFCAP_TSO6)
|
||||
#define T4_CAP_ENABLE (T4_CAP)
|
||||
|
||||
static int
|
||||
cxgbe_attach(device_t dev)
|
||||
@ -1075,7 +1076,7 @@ cxgbe_ioctl(struct ifnet *ifp, unsigned long cmd, caddr_t data)
|
||||
ifp->if_capenable ^= IFCAP_TSO6;
|
||||
}
|
||||
if (mask & IFCAP_LRO) {
|
||||
#ifdef INET
|
||||
#if defined(INET) || defined(INET6)
|
||||
int i;
|
||||
struct sge_rxq *rxq;
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_inet6.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/mbuf.h>
|
||||
@ -46,6 +47,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <net/if_vlan_var.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#include "common/common.h"
|
||||
@ -908,7 +910,7 @@ service_iq(struct sge_iq *iq, int budget)
|
||||
STAILQ_INSERT_TAIL(&iql, q, link);
|
||||
}
|
||||
|
||||
#ifdef INET
|
||||
#if defined(INET) || defined(INET6)
|
||||
if (iq->flags & IQ_LRO_ENABLED) {
|
||||
struct lro_ctrl *lro = &rxq->lro;
|
||||
struct lro_entry *l;
|
||||
@ -1039,7 +1041,7 @@ t4_eth_rx(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m0)
|
||||
struct sge_rxq *rxq = iq_to_rxq(iq);
|
||||
struct ifnet *ifp = rxq->ifp;
|
||||
const struct cpl_rx_pkt *cpl = (const void *)(rss + 1);
|
||||
#ifdef INET
|
||||
#if defined(INET) || defined(INET6)
|
||||
struct lro_ctrl *lro = &rxq->lro;
|
||||
#endif
|
||||
|
||||
@ -1079,7 +1081,7 @@ t4_eth_rx(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m0)
|
||||
rxq->vlan_extraction++;
|
||||
}
|
||||
|
||||
#ifdef INET
|
||||
#if defined(INET) || defined(INET6)
|
||||
if (cpl->l2info & htobe32(F_RXF_LRO) &&
|
||||
iq->flags & IQ_LRO_ENABLED &&
|
||||
tcp_lro_rx(lro, m0, 0) == 0) {
|
||||
@ -1805,7 +1807,7 @@ alloc_rxq(struct port_info *pi, struct sge_rxq *rxq, int intr_idx, int idx,
|
||||
refill_fl(pi->adapter, &rxq->fl, rxq->fl.needed / 8);
|
||||
FL_UNLOCK(&rxq->fl);
|
||||
|
||||
#ifdef INET
|
||||
#if defined(INET) || defined(INET6)
|
||||
rc = tcp_lro_init(&rxq->lro);
|
||||
if (rc != 0)
|
||||
return (rc);
|
||||
@ -1832,7 +1834,7 @@ alloc_rxq(struct port_info *pi, struct sge_rxq *rxq, int intr_idx, int idx,
|
||||
SYSCTL_ADD_PROC(&pi->ctx, children, OID_AUTO, "cidx",
|
||||
CTLTYPE_INT | CTLFLAG_RD, &rxq->iq.cidx, 0, sysctl_uint16, "I",
|
||||
"consumer index");
|
||||
#ifdef INET
|
||||
#if defined(INET) || defined(INET6)
|
||||
SYSCTL_ADD_INT(&pi->ctx, children, OID_AUTO, "lro_queued", CTLFLAG_RD,
|
||||
&rxq->lro.lro_queued, 0, NULL);
|
||||
SYSCTL_ADD_INT(&pi->ctx, children, OID_AUTO, "lro_flushed", CTLFLAG_RD,
|
||||
@ -1865,7 +1867,7 @@ free_rxq(struct port_info *pi, struct sge_rxq *rxq)
|
||||
{
|
||||
int rc;
|
||||
|
||||
#ifdef INET
|
||||
#if defined(INET) || defined(INET6)
|
||||
if (rxq->lro.ifp) {
|
||||
tcp_lro_free(&rxq->lro);
|
||||
rxq->lro.ifp = NULL;
|
||||
@ -2273,7 +2275,7 @@ alloc_txq(struct port_info *pi, struct sge_txq *txq, int idx,
|
||||
CTLFLAG_RD, &txq->vlan_insertion,
|
||||
"# of times hardware inserted 802.1Q tag");
|
||||
SYSCTL_ADD_UQUAD(&pi->ctx, children, OID_AUTO, "tso_wrs", CTLFLAG_RD,
|
||||
&txq->tso_wrs, "# of IPv4 TSO work requests");
|
||||
&txq->tso_wrs, "# of TSO work requests");
|
||||
SYSCTL_ADD_UQUAD(&pi->ctx, children, OID_AUTO, "imm_wrs", CTLFLAG_RD,
|
||||
&txq->imm_wrs, "# of work requests with immediate data");
|
||||
SYSCTL_ADD_UQUAD(&pi->ctx, children, OID_AUTO, "sgl_wrs", CTLFLAG_RD,
|
||||
@ -2802,22 +2804,60 @@ write_txpkt_wr(struct port_info *pi, struct sge_txq *txq, struct mbuf *m,
|
||||
if (m->m_pkthdr.tso_segsz) {
|
||||
struct cpl_tx_pkt_lso_core *lso = (void *)(wr + 1);
|
||||
struct ether_header *eh;
|
||||
struct ip *ip;
|
||||
void *l3hdr;
|
||||
#if defined(INET) || defined(INET6)
|
||||
struct tcphdr *tcp;
|
||||
#endif
|
||||
uint16_t eh_type;
|
||||
|
||||
ctrl = V_LSO_OPCODE(CPL_TX_PKT_LSO) | F_LSO_FIRST_SLICE |
|
||||
F_LSO_LAST_SLICE;
|
||||
|
||||
eh = mtod(m, struct ether_header *);
|
||||
if (eh->ether_type == htons(ETHERTYPE_VLAN)) {
|
||||
ctrl |= V_LSO_ETHHDR_LEN(1);
|
||||
ip = (void *)((struct ether_vlan_header *)eh + 1);
|
||||
} else
|
||||
ip = (void *)(eh + 1);
|
||||
eh_type = ntohs(eh->ether_type);
|
||||
if (eh_type == ETHERTYPE_VLAN) {
|
||||
struct ether_vlan_header *evh = (void *)eh;
|
||||
|
||||
tcp = (void *)((uintptr_t)ip + ip->ip_hl * 4);
|
||||
ctrl |= V_LSO_IPHDR_LEN(ip->ip_hl) |
|
||||
V_LSO_TCPHDR_LEN(tcp->th_off);
|
||||
ctrl |= V_LSO_ETHHDR_LEN(1);
|
||||
l3hdr = evh + 1;
|
||||
eh_type = ntohs(evh->evl_proto);
|
||||
} else
|
||||
l3hdr = eh + 1;
|
||||
|
||||
switch (eh_type) {
|
||||
#ifdef INET6
|
||||
case ETHERTYPE_IPV6:
|
||||
{
|
||||
struct ip6_hdr *ip6 = l3hdr;
|
||||
|
||||
/*
|
||||
* XXX-BZ For now we do not pretend to support
|
||||
* IPv6 extension headers.
|
||||
*/
|
||||
KASSERT(ip6->ip6_nxt == IPPROTO_TCP, ("%s: CSUM_TSO "
|
||||
"with ip6_nxt != TCP: %u", __func__, ip6->ip6_nxt));
|
||||
tcp = (struct tcphdr *)(ip6 + 1);
|
||||
ctrl |= F_LSO_IPV6;
|
||||
ctrl |= V_LSO_IPHDR_LEN(sizeof(*ip6) >> 2) |
|
||||
V_LSO_TCPHDR_LEN(tcp->th_off);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef INET
|
||||
case ETHERTYPE_IP:
|
||||
{
|
||||
struct ip *ip = l3hdr;
|
||||
|
||||
tcp = (void *)((uintptr_t)ip + ip->ip_hl * 4);
|
||||
ctrl |= V_LSO_IPHDR_LEN(ip->ip_hl) |
|
||||
V_LSO_TCPHDR_LEN(tcp->th_off);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
panic("%s: CSUM_TSO but no supported IP version "
|
||||
"(0x%04x)", __func__, eh_type);
|
||||
}
|
||||
|
||||
lso->lso_ctrl = htobe32(ctrl);
|
||||
lso->ipid_ofst = htobe16(0);
|
||||
|
@ -9,7 +9,7 @@ KMOD = if_cxgbe
|
||||
SRCS = t4_main.c t4_sge.c t4_l2t.c
|
||||
SRCS+= t4_hw.c
|
||||
SRCS+= device_if.h bus_if.h pci_if.h
|
||||
SRCS+= opt_inet.h
|
||||
SRCS+= opt_inet.h opt_inet6.h
|
||||
SRCS+= opt_ofed.h
|
||||
|
||||
CFLAGS+= -I${CXGBE}
|
||||
|
Loading…
Reference in New Issue
Block a user