Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/cxgbe/tom/t4_listen.c
Show First 20 Lines • Show All 982 Lines • ▼ Show 20 Lines | if (t4opt->tstamp) | ||||
to->to_flags |= TOF_TS; | to->to_flags |= TOF_TS; | ||||
if (t4opt->sack) | if (t4opt->sack) | ||||
to->to_flags |= TOF_SACKPERM; | to->to_flags |= TOF_SACKPERM; | ||||
} | } | ||||
static void | static void | ||||
pass_accept_req_to_protohdrs(struct adapter *sc, const struct mbuf *m, | pass_accept_req_to_protohdrs(struct adapter *sc, const struct mbuf *m, | ||||
struct in_conninfo *inc, struct tcphdr *th) | struct in_conninfo *inc, struct tcphdr *th, uint8_t *iptos) | ||||
{ | { | ||||
const struct cpl_pass_accept_req *cpl = mtod(m, const void *); | const struct cpl_pass_accept_req *cpl = mtod(m, const void *); | ||||
const struct ether_header *eh; | const struct ether_header *eh; | ||||
unsigned int hlen = be32toh(cpl->hdr_len); | unsigned int hlen = be32toh(cpl->hdr_len); | ||||
uintptr_t l3hdr; | uintptr_t l3hdr; | ||||
const struct tcphdr *tcp; | const struct tcphdr *tcp; | ||||
eh = (const void *)(cpl + 1); | eh = (const void *)(cpl + 1); | ||||
if (chip_id(sc) >= CHELSIO_T6) { | if (chip_id(sc) >= CHELSIO_T6) { | ||||
l3hdr = ((uintptr_t)eh + G_T6_ETH_HDR_LEN(hlen)); | l3hdr = ((uintptr_t)eh + G_T6_ETH_HDR_LEN(hlen)); | ||||
tcp = (const void *)(l3hdr + G_T6_IP_HDR_LEN(hlen)); | tcp = (const void *)(l3hdr + G_T6_IP_HDR_LEN(hlen)); | ||||
} else { | } else { | ||||
l3hdr = ((uintptr_t)eh + G_ETH_HDR_LEN(hlen)); | l3hdr = ((uintptr_t)eh + G_ETH_HDR_LEN(hlen)); | ||||
tcp = (const void *)(l3hdr + G_IP_HDR_LEN(hlen)); | tcp = (const void *)(l3hdr + G_IP_HDR_LEN(hlen)); | ||||
} | } | ||||
/* extract TOS (DiffServ + ECN) byte for AccECN */ | |||||
if (iptos) { | |||||
if (((struct ip *)l3hdr)->ip_v == IPVERSION) { | |||||
const struct ip *ip = (const void *)l3hdr; | |||||
*iptos = ip->ip_tos; | |||||
} | |||||
#ifdef INET6 | |||||
else | |||||
if (((struct ip *)l3hdr)->ip_v == (IPV6_VERSION >> 4)) { | |||||
const struct ip6_hdr *ip6 = (const void *)l3hdr; | |||||
*iptos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; | |||||
} | |||||
#endif /* INET */ | |||||
} | |||||
if (inc) { | if (inc) { | ||||
bzero(inc, sizeof(*inc)); | bzero(inc, sizeof(*inc)); | ||||
inc->inc_fport = tcp->th_sport; | inc->inc_fport = tcp->th_sport; | ||||
inc->inc_lport = tcp->th_dport; | inc->inc_lport = tcp->th_dport; | ||||
if (((struct ip *)l3hdr)->ip_v == IPVERSION) { | if (((struct ip *)l3hdr)->ip_v == IPVERSION) { | ||||
const struct ip *ip = (const void *)l3hdr; | const struct ip *ip = (const void *)l3hdr; | ||||
inc->inc_faddr = ip->ip_src; | inc->inc_faddr = ip->ip_src; | ||||
▲ Show 20 Lines • Show All 129 Lines • ▼ Show 20 Lines | do_pass_accept_req(struct sge_iq *iq, const struct rss_header *rss, | ||||
struct synq_entry *synqe = NULL; | struct synq_entry *synqe = NULL; | ||||
int reject_reason, v, ntids; | int reject_reason, v, ntids; | ||||
uint16_t vid, l2info; | uint16_t vid, l2info; | ||||
struct epoch_tracker et; | struct epoch_tracker et; | ||||
#ifdef INVARIANTS | #ifdef INVARIANTS | ||||
unsigned int opcode = G_CPL_OPCODE(be32toh(OPCODE_TID(cpl))); | unsigned int opcode = G_CPL_OPCODE(be32toh(OPCODE_TID(cpl))); | ||||
#endif | #endif | ||||
struct offload_settings settings; | struct offload_settings settings; | ||||
uint8_t iptos; | |||||
KASSERT(opcode == CPL_PASS_ACCEPT_REQ, | KASSERT(opcode == CPL_PASS_ACCEPT_REQ, | ||||
("%s: unexpected opcode 0x%x", __func__, opcode)); | ("%s: unexpected opcode 0x%x", __func__, opcode)); | ||||
KASSERT(lctx->stid == stid, ("%s: lctx stid mismatch", __func__)); | KASSERT(lctx->stid == stid, ("%s: lctx stid mismatch", __func__)); | ||||
CTR4(KTR_CXGBE, "%s: stid %u, tid %u, lctx %p", __func__, stid, tid, | CTR4(KTR_CXGBE, "%s: stid %u, tid %u, lctx %p", __func__, stid, tid, | ||||
lctx); | lctx); | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | found: | ||||
/* | /* | ||||
* Don't offload if the ifnet that the SYN came in on is not in the same | * Don't offload if the ifnet that the SYN came in on is not in the same | ||||
* vnet as the listening socket. | * vnet as the listening socket. | ||||
*/ | */ | ||||
if (lctx->vnet != ifp->if_vnet) | if (lctx->vnet != ifp->if_vnet) | ||||
REJECT_PASS_ACCEPT_REQ(true); | REJECT_PASS_ACCEPT_REQ(true); | ||||
pass_accept_req_to_protohdrs(sc, m, &inc, &th); | pass_accept_req_to_protohdrs(sc, m, &inc, &th, &iptos); | ||||
if (inc.inc_flags & INC_ISIPV6) { | if (inc.inc_flags & INC_ISIPV6) { | ||||
/* Don't offload if the ifcap isn't enabled */ | /* Don't offload if the ifcap isn't enabled */ | ||||
if ((ifp->if_capenable & IFCAP_TOE6) == 0) | if ((ifp->if_capenable & IFCAP_TOE6) == 0) | ||||
REJECT_PASS_ACCEPT_REQ(true); | REJECT_PASS_ACCEPT_REQ(true); | ||||
/* | /* | ||||
* SYN must be directed to an IP6 address on this ifnet. This | * SYN must be directed to an IP6 address on this ifnet. This | ||||
▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | found: | ||||
init_conn_params(vi, &settings, &inc, so, &cpl->tcpopt, e->idx, | init_conn_params(vi, &settings, &inc, so, &cpl->tcpopt, e->idx, | ||||
&synqe->params); | &synqe->params); | ||||
/* | /* | ||||
* If all goes well t4_syncache_respond will get called during | * If all goes well t4_syncache_respond will get called during | ||||
* syncache_add. Note that syncache_add releases the pcb lock. | * syncache_add. Note that syncache_add releases the pcb lock. | ||||
*/ | */ | ||||
t4opt_to_tcpopt(&cpl->tcpopt, &to); | t4opt_to_tcpopt(&cpl->tcpopt, &to); | ||||
toe_syncache_add(&inc, &to, &th, inp, tod, synqe); | toe_syncache_add(&inc, &to, &th, inp, tod, synqe, iptos); | ||||
if (atomic_load_int(&synqe->ok_to_respond) > 0) { | if (atomic_load_int(&synqe->ok_to_respond) > 0) { | ||||
uint64_t opt0; | uint64_t opt0; | ||||
uint32_t opt2; | uint32_t opt2; | ||||
opt0 = calc_options0(vi, &synqe->params); | opt0 = calc_options0(vi, &synqe->params); | ||||
opt2 = calc_options2(vi, &synqe->params); | opt2 = calc_options2(vi, &synqe->params); | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
static void | static void | ||||
synqe_to_protohdrs(struct adapter *sc, struct synq_entry *synqe, | synqe_to_protohdrs(struct adapter *sc, struct synq_entry *synqe, | ||||
const struct cpl_pass_establish *cpl, struct in_conninfo *inc, | const struct cpl_pass_establish *cpl, struct in_conninfo *inc, | ||||
struct tcphdr *th, struct tcpopt *to) | struct tcphdr *th, struct tcpopt *to) | ||||
{ | { | ||||
uint16_t tcp_opt = be16toh(cpl->tcp_opt); | uint16_t tcp_opt = be16toh(cpl->tcp_opt); | ||||
uint8_t iptos; | |||||
/* start off with the original SYN */ | /* start off with the original SYN */ | ||||
pass_accept_req_to_protohdrs(sc, synqe->syn, inc, th); | pass_accept_req_to_protohdrs(sc, synqe->syn, inc, th, &iptos); | ||||
/* modify parts to make it look like the ACK to our SYN|ACK */ | /* modify parts to make it look like the ACK to our SYN|ACK */ | ||||
th->th_flags = TH_ACK; | th->th_flags = TH_ACK; | ||||
th->th_ack = synqe->iss + 1; | th->th_ack = synqe->iss + 1; | ||||
th->th_seq = be32toh(cpl->rcv_isn); | th->th_seq = be32toh(cpl->rcv_isn); | ||||
bzero(to, sizeof(*to)); | bzero(to, sizeof(*to)); | ||||
if (G_TCPOPT_TSTAMP(tcp_opt)) { | if (G_TCPOPT_TSTAMP(tcp_opt)) { | ||||
to->to_flags |= TOF_TS; | to->to_flags |= TOF_TS; | ||||
▲ Show 20 Lines • Show All 138 Lines • Show Last 20 Lines |