diff options
Diffstat (limited to 'sys/dev/mlx5/mlx5_en/mlx5_en_rx.c')
-rw-r--r-- | sys/dev/mlx5/mlx5_en/mlx5_en_rx.c | 102 |
1 files changed, 80 insertions, 22 deletions
diff --git a/sys/dev/mlx5/mlx5_en/mlx5_en_rx.c b/sys/dev/mlx5/mlx5_en/mlx5_en_rx.c index b52dee102a3d..6b53db6fea23 100644 --- a/sys/dev/mlx5/mlx5_en/mlx5_en_rx.c +++ b/sys/dev/mlx5/mlx5_en/mlx5_en_rx.c @@ -27,7 +27,9 @@ #include "opt_ratelimit.h" #include <dev/mlx5/mlx5_en/en.h> +#include <netinet/ip_var.h> #include <machine/in_cksum.h> +#include <dev/mlx5/mlx5_accel/ipsec.h> static inline int mlx5e_alloc_rx_wqe(struct mlx5e_rq *rq, @@ -43,25 +45,21 @@ mlx5e_alloc_rx_wqe(struct mlx5e_rq *rq, if (rq->mbuf[ix].mbuf != NULL) return (0); - mb_head = mb = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, - MLX5E_MAX_RX_BYTES); + mb_head = mb = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, rq->wqe_sz); if (unlikely(mb == NULL)) return (-ENOMEM); - mb->m_len = MLX5E_MAX_RX_BYTES; - mb->m_pkthdr.len = MLX5E_MAX_RX_BYTES; + mb->m_len = rq->wqe_sz; + mb->m_pkthdr.len = rq->wqe_sz; for (i = 1; i < rq->nsegs; i++) { - if (mb_head->m_pkthdr.len >= rq->wqe_sz) - break; - mb = mb->m_next = m_getjcl(M_NOWAIT, MT_DATA, 0, - MLX5E_MAX_RX_BYTES); + mb = mb->m_next = m_getjcl(M_NOWAIT, MT_DATA, 0, rq->wqe_sz); if (unlikely(mb == NULL)) { m_freem(mb_head); return (-ENOMEM); } - mb->m_len = MLX5E_MAX_RX_BYTES; - mb_head->m_pkthdr.len += MLX5E_MAX_RX_BYTES; + mb->m_len = rq->wqe_sz; + mb_head->m_pkthdr.len += rq->wqe_sz; } /* rewind to first mbuf in chain */ mb = mb_head; @@ -69,6 +67,9 @@ mlx5e_alloc_rx_wqe(struct mlx5e_rq *rq, /* get IP header aligned */ m_adj(mb, MLX5E_NET_IP_ALIGN); + err = mlx5_accel_ipsec_rx_tag_add(rq->ifp, &rq->mbuf[ix]); + if (err) + goto err_free_mbuf; err = -bus_dmamap_load_mbuf_sg(rq->dma_tag, rq->mbuf[ix].dma_map, mb, segs, &nsegs, BUS_DMA_NOWAIT); if (err != 0) @@ -124,6 +125,27 @@ mlx5e_post_rx_wqes(struct mlx5e_rq *rq) mlx5_wq_ll_update_db_record(&rq->wq); } +static uint32_t +csum_reduce(uint32_t val) +{ + while (val > 0xffff) + val = (val >> 16) + (val & 0xffff); + return (val); +} + +static u_short +csum_buf(uint32_t val, void *buf, int len) +{ + u_short x; + + MPASS(len % 2 == 0); + for (int i = 0; i < len; i += 2) { + bcopy((char *)buf + i, &x, 2); + val = csum_reduce(val + x); + } + return (val); +} + static void mlx5e_lro_update_hdr(struct mbuf *mb, struct mlx5_cqe64 *cqe) { @@ -135,6 +157,7 @@ mlx5e_lro_update_hdr(struct mbuf *mb, struct mlx5_cqe64 *cqe) struct ip *ip4 = NULL; struct tcphdr *th; uint32_t *ts_ptr; + uint32_t tcp_csum; uint8_t l4_hdr_type; int tcp_ack; @@ -164,10 +187,10 @@ mlx5e_lro_update_hdr(struct mbuf *mb, struct mlx5_cqe64 *cqe) ts_ptr = (uint32_t *)(th + 1); if (get_cqe_lro_tcppsh(cqe)) - th->th_flags |= TH_PUSH; + tcp_set_flags(th, tcp_get_flags(th) | TH_PUSH); if (tcp_ack) { - th->th_flags |= TH_ACK; + tcp_set_flags(th, tcp_get_flags(th) | TH_ACK); th->th_ack = cqe->lro_ack_seq_num; th->th_win = cqe->lro_tcp_win; @@ -183,29 +206,55 @@ mlx5e_lro_update_hdr(struct mbuf *mb, struct mlx5_cqe64 *cqe) * +--------+--------+--------+--------+ */ if (get_cqe_lro_timestamp_valid(cqe) && - (__predict_true(*ts_ptr) == ntohl(TCPOPT_NOP << 24 | + (__predict_true(*ts_ptr == ntohl(TCPOPT_NOP << 24 | TCPOPT_NOP << 16 | TCPOPT_TIMESTAMP << 8 | - TCPOLEN_TIMESTAMP))) { + TCPOLEN_TIMESTAMP)))) { /* * cqe->timestamp is 64bit long. * [0-31] - timestamp. * [32-64] - timestamp echo replay. */ - ts_ptr[1] = *(uint32_t *)&cqe->timestamp; ts_ptr[2] = *((uint32_t *)&cqe->timestamp + 1); } } if (ip4) { + struct ipovly io; + ip4->ip_ttl = cqe->lro_min_ttl; ip4->ip_len = cpu_to_be16(tot_len); ip4->ip_sum = 0; - ip4->ip_sum = in_cksum(mb, ip4->ip_hl << 2); + ip4->ip_sum = in_cksum_skip(mb, (ip4->ip_hl << 2) + + ETHER_HDR_LEN, ETHER_HDR_LEN); + + /* TCP checksum: data */ + tcp_csum = cqe->check_sum; + + /* TCP checksum: IP pseudoheader */ + bzero(io.ih_x1, sizeof(io.ih_x1)); + io.ih_pr = IPPROTO_TCP; + io.ih_len = htons(ntohs(ip4->ip_len) - sizeof(*ip4)); + io.ih_src = ip4->ip_src; + io.ih_dst = ip4->ip_dst; + tcp_csum = csum_buf(tcp_csum, &io, sizeof(io)); + + /* TCP checksum: TCP header */ + th->th_sum = 0; + tcp_csum = csum_buf(tcp_csum, th, th->th_off * 4); + th->th_sum = ~tcp_csum & 0xffff; } else { ip6->ip6_hlim = cqe->lro_min_ttl; ip6->ip6_plen = cpu_to_be16(tot_len - sizeof(struct ip6_hdr)); + + /* TCP checksum */ + th->th_sum = 0; + tcp_csum = ~in6_cksum_partial_l2(mb, IPPROTO_TCP, + sizeof(struct ether_header), + sizeof(struct ether_header) + sizeof(struct ip6_hdr), + tot_len - sizeof(struct ip6_hdr), th->th_off * 4) & 0xffff; + tcp_csum = csum_reduce(tcp_csum + cqe->check_sum); + th->th_sum = ~tcp_csum & 0xffff; } - /* TODO: handle tcp checksum */ } static uint64_t @@ -273,9 +322,8 @@ mlx5e_mbuf_tstmp(struct mlx5e_priv *priv, uint64_t hw_tstmp) } static inline void -mlx5e_build_rx_mbuf(struct mlx5_cqe64 *cqe, - struct mlx5e_rq *rq, struct mbuf *mb, - u32 cqe_bcnt) +mlx5e_build_rx_mbuf(struct mlx5_cqe64 *cqe, struct mlx5e_rq *rq, + struct mbuf *mb, struct mlx5e_rq_mbuf *mr, u32 cqe_bcnt) { if_t ifp = rq->ifp; struct mlx5e_channel *c; @@ -418,6 +466,8 @@ mlx5e_build_rx_mbuf(struct mlx5_cqe64 *cqe, default: break; } + + mlx5e_accel_ipsec_handle_rx(mb, cqe, mr); } static inline void @@ -563,7 +613,9 @@ mlx5e_poll_rx_cq(struct mlx5e_rq *rq, int budget) ("Filter returned %d!\n", rv)); } } - if ((MHLEN - MLX5E_NET_IP_ALIGN) >= byte_cnt && + if (!mlx5e_accel_ipsec_flow(cqe) /* tag is already assigned + to rq->mbuf */ && + MHLEN - MLX5E_NET_IP_ALIGN >= byte_cnt && (mb = m_gethdr(M_NOWAIT, MT_DATA)) != NULL) { /* set maximum mbuf length */ mb->m_len = MHLEN - MLX5E_NET_IP_ALIGN; @@ -580,7 +632,8 @@ mlx5e_poll_rx_cq(struct mlx5e_rq *rq, int budget) rq->mbuf[wqe_counter].dma_map); } rx_common: - mlx5e_build_rx_mbuf(cqe, rq, mb, byte_cnt); + mlx5e_build_rx_mbuf(cqe, rq, mb, &rq->mbuf[wqe_counter], + byte_cnt); rq->stats.bytes += byte_cnt; rq->stats.packets++; #ifdef NUMA @@ -644,6 +697,9 @@ mlx5e_rx_cq_comp(struct mlx5_core_cq *mcq, struct mlx5_eqe *eqe __unused) mtx_unlock(&c->iq.lock); mtx_lock(&rq->mtx); + if (rq->enabled == 0) + goto out; + rq->processing++; /* * Polling the entire CQ without posting new WQEs results in @@ -664,6 +720,8 @@ mlx5e_rx_cq_comp(struct mlx5_core_cq *mcq, struct mlx5_eqe *eqe __unused) net_dim(&rq->dim, rq->stats.packets, rq->stats.bytes); mlx5e_cq_arm(&rq->cq, MLX5_GET_DOORBELL_LOCK(&rq->channel->priv->doorbell_lock)); tcp_lro_flush_all(&rq->lro); + rq->processing--; +out: mtx_unlock(&rq->mtx); for (int j = 0; j != MLX5E_MAX_TX_NUM_TC; j++) { |