mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-19 06:44:31 +00:00
Add IPv6 TSO (including TSO+VLAN) support to cxgb(4).
If an IPv6 packet has extension headers the kernel needs to deal with it itself. For the rest it can set various CSUM_XXX flags and the driver will act on them.
This commit is contained in:
parent
8d26fe2af5
commit
3e7cc3cab3
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=231317
|
@ -982,7 +982,7 @@ cxgb_makedev(struct port_info *pi)
|
|||
#define CXGB_CAP (IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU | IFCAP_HWCSUM | \
|
||||
IFCAP_VLAN_HWCSUM | IFCAP_TSO | IFCAP_JUMBO_MTU | IFCAP_LRO | \
|
||||
IFCAP_VLAN_HWTSO | IFCAP_LINKSTATE)
|
||||
#define CXGB_CAP_ENABLE (CXGB_CAP & ~IFCAP_TSO6)
|
||||
#define CXGB_CAP_ENABLE CXGB_CAP
|
||||
|
||||
static int
|
||||
cxgb_port_attach(device_t dev)
|
||||
|
@ -2059,8 +2059,8 @@ cxgb_ioctl(struct ifnet *ifp, unsigned long command, caddr_t data)
|
|||
}
|
||||
if (mask & IFCAP_RXCSUM)
|
||||
ifp->if_capenable ^= IFCAP_RXCSUM;
|
||||
if (mask & IFCAP_TSO4) {
|
||||
ifp->if_capenable ^= IFCAP_TSO4;
|
||||
if (mask & IFCAP_TSO) {
|
||||
ifp->if_capenable ^= IFCAP_TSO;
|
||||
|
||||
if (IFCAP_TSO & ifp->if_capenable) {
|
||||
if (IFCAP_TXCSUM & ifp->if_capenable)
|
||||
|
|
|
@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
|
|||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#include <dev/pci/pcireg.h>
|
||||
|
@ -1492,10 +1493,10 @@ t3_encap(struct sge_qset *qs, struct mbuf **m)
|
|||
check_ring_tx_db(sc, txq, 0);
|
||||
return (0);
|
||||
} else if (tso_info) {
|
||||
int eth_type;
|
||||
uint16_t eth_type;
|
||||
struct cpl_tx_pkt_lso *hdr = (struct cpl_tx_pkt_lso *)txd;
|
||||
struct ether_header *eh;
|
||||
struct ip *ip;
|
||||
void *l3hdr;
|
||||
struct tcphdr *tcp;
|
||||
|
||||
txd->flit[2] = 0;
|
||||
|
@ -1521,18 +1522,37 @@ t3_encap(struct sge_qset *qs, struct mbuf **m)
|
|||
}
|
||||
|
||||
eh = mtod(m0, struct ether_header *);
|
||||
if (eh->ether_type == htons(ETHERTYPE_VLAN)) {
|
||||
eth_type = CPL_ETH_II_VLAN;
|
||||
ip = (struct ip *)((struct ether_vlan_header *)eh + 1);
|
||||
} else {
|
||||
eth_type = CPL_ETH_II;
|
||||
ip = (struct ip *)(eh + 1);
|
||||
}
|
||||
tcp = (struct tcphdr *)(ip + 1);
|
||||
eth_type = eh->ether_type;
|
||||
if (eth_type == htons(ETHERTYPE_VLAN)) {
|
||||
struct ether_vlan_header *evh = (void *)eh;
|
||||
|
||||
tso_info |= V_LSO_ETH_TYPE(eth_type) |
|
||||
V_LSO_IPHDR_WORDS(ip->ip_hl) |
|
||||
V_LSO_TCPHDR_WORDS(tcp->th_off);
|
||||
tso_info |= V_LSO_ETH_TYPE(CPL_ETH_II_VLAN);
|
||||
l3hdr = evh + 1;
|
||||
eth_type = evh->evl_proto;
|
||||
} else {
|
||||
tso_info |= V_LSO_ETH_TYPE(CPL_ETH_II);
|
||||
l3hdr = eh + 1;
|
||||
}
|
||||
|
||||
if (eth_type == htons(ETHERTYPE_IP)) {
|
||||
struct ip *ip = l3hdr;
|
||||
|
||||
tso_info |= V_LSO_IPHDR_WORDS(ip->ip_hl);
|
||||
tcp = (struct tcphdr *)(ip + 1);
|
||||
} else if (eth_type == htons(ETHERTYPE_IPV6)) {
|
||||
struct ip6_hdr *ip6 = l3hdr;
|
||||
|
||||
KASSERT(ip6->ip6_nxt == IPPROTO_TCP,
|
||||
("%s: CSUM_TSO with ip6_nxt %d",
|
||||
__func__, ip6->ip6_nxt));
|
||||
|
||||
tso_info |= F_LSO_IPV6;
|
||||
tso_info |= V_LSO_IPHDR_WORDS(sizeof(*ip6) >> 2);
|
||||
tcp = (struct tcphdr *)(ip6 + 1);
|
||||
} else
|
||||
panic("%s: CSUM_TSO but neither ip nor ip6", __func__);
|
||||
|
||||
tso_info |= V_LSO_TCPHDR_WORDS(tcp->th_off);
|
||||
hdr->lso_info = htonl(tso_info);
|
||||
|
||||
if (__predict_false(mlen <= PIO_LEN)) {
|
||||
|
|
Loading…
Reference in a new issue