int enic_send_pkt(struct enic *enic, struct vnic_wq *wq, struct rte_mbuf *tx_pkt, unsigned short len, uint8_t sop, uint8_t eop, uint16_t ol_flags, uint16_t vlan_tag) { struct wq_enet_desc *desc = vnic_wq_next_desc(wq); uint16_t mss = 0; uint8_t cq_entry = eop; uint8_t vlan_tag_insert = 0; uint64_t bus_addr = (dma_addr_t) (tx_pkt->buf_physaddr + RTE_PKTMBUF_HEADROOM); if (sop) { if (ol_flags & PKT_TX_VLAN_PKT) vlan_tag_insert = 1; if (enic->hw_ip_checksum) { if (ol_flags & PKT_TX_IP_CKSUM) mss |= ENIC_CALC_IP_CKSUM; if (ol_flags & PKT_TX_TCP_UDP_CKSUM) mss |= ENIC_CALC_TCP_UDP_CKSUM; } } wq_enet_desc_enc(desc, bus_addr, len, mss, 0 /* header_length */, 0 /* offload_mode WQ_ENET_OFFLOAD_MODE_CSUM */, eop, cq_entry, 0 /* fcoe_encap */, vlan_tag_insert, vlan_tag, 0 /* loopback */); vnic_wq_post(wq, (void *)tx_pkt, bus_addr, len, sop, eop, 1 /*desc_skip_cnt*/, cq_entry, 0 /*compressed send*/, 0 /*wrid*/); return 0; }
static inline void usdf_msg_send_segment(struct usdf_tx *tx, struct usdf_ep *ep) { struct usdf_msg_qe *msg; struct rudp_pkt *hdr; struct usd_wq *wq; uint32_t index; size_t cur_iov; size_t cur_resid; size_t resid; const uint8_t *cur_ptr; const uint8_t *send_ptr; size_t sge_len; uint8_t *ptr; struct usd_wq_post_info *info; msg = TAILQ_FIRST(&ep->e.msg.ep_posted_wqe); wq = &(to_qpi(tx->tx_qp)->uq_wq); index = wq->uwq_post_index; hdr = (struct rudp_pkt *)(wq->uwq_copybuf + index * USD_SEND_MAX_COPY); memcpy(hdr, &ep->e.msg.ep_dest->ds_dest.ds_udp.u_hdr, sizeof(struct usd_udp_hdr)); hdr->msg.src_peer_id = htons(ep->e.msg.ep_lcl_peer_id); resid = msg->ms_resid; cur_iov = msg->ms_cur_iov; cur_ptr = msg->ms_cur_ptr; cur_resid = msg->ms_iov_resid; /* save first seq for message */ if (cur_iov == 0 && cur_resid == msg->ms_iov[0].iov_len) { msg->ms_first_seq = ep->e.msg.ep_next_tx_seq; } if (resid < USD_SEND_MAX_COPY - sizeof(*hdr)) { hdr->msg.opcode = htons(RUDP_OP_LAST); hdr->msg.m.rc_data.length = htons(resid); hdr->msg.m.rc_data.seqno = htons(ep->e.msg.ep_next_tx_seq); ++ep->e.msg.ep_next_tx_seq; sge_len = resid; ptr = (uint8_t *)(hdr + 1); while (resid > 0) { memcpy(ptr, cur_ptr, cur_resid); ptr += cur_resid; resid -= cur_resid; ++cur_iov; cur_ptr = msg->ms_iov[cur_iov].iov_base; cur_resid = msg->ms_iov[cur_iov].iov_len; } /* add packet lengths */ hdr->hdr.uh_ip.tot_len = htons( sge_len + sizeof(struct rudp_pkt) - sizeof(struct ether_header)); hdr->hdr.uh_udp.len = htons( (sizeof(struct rudp_pkt) - sizeof(struct ether_header) - sizeof(struct iphdr)) + sge_len); index = _usd_post_send_one(wq, hdr, sge_len + sizeof(*hdr), 1); } else { struct vnic_wq *vwq; u_int8_t offload_mode = 0, eop; u_int16_t mss = 7, header_length = 0, vlan_tag = 0; u_int8_t vlan_tag_insert = 0, loopback = 0, fcoe_encap = 0; struct wq_enet_desc *desc; size_t space; size_t num_sge; size_t sent; vwq = &wq->uwq_vnic_wq; desc = wq->uwq_next_desc; space = ep->ep_domain->dom_fabric->fab_dev_attrs->uda_mtu - sizeof(*hdr); num_sge = 1; /* encode header desc */ eop = 0; wq_enet_desc_enc(desc, (uintptr_t)hdr, sizeof(*hdr), mss, header_length, offload_mode, eop, 0, fcoe_encap, vlan_tag_insert, vlan_tag, loopback); do { desc = (struct wq_enet_desc *) ((uintptr_t)wq->uwq_desc_ring + (index << 4)); index = (index + 1) & wq->uwq_post_index_mask; send_ptr = cur_ptr; if (cur_resid >= space) { sge_len = space; eop = 1; cur_resid -= sge_len; cur_ptr += sge_len; } else { sge_len = cur_resid; if (num_sge == USDF_MSG_MAX_SGE || cur_resid == resid) { eop = 1; } ++cur_iov; cur_ptr = msg->ms_iov[cur_iov].iov_base; cur_resid = msg->ms_iov[cur_iov].iov_len; } wq_enet_desc_enc(desc, (uintptr_t)send_ptr, sge_len, mss, header_length, offload_mode, eop, eop, fcoe_encap, vlan_tag_insert, vlan_tag, loopback); ++num_sge; space -= sge_len; resid -= sge_len; } while (space > 0 && num_sge <= USDF_MSG_MAX_SGE && resid > 0); /* add packet lengths */ sent = ep->ep_domain->dom_fabric->fab_dev_attrs->uda_mtu - sizeof(*hdr) - space; hdr->hdr.uh_ip.tot_len = htons( sent + sizeof(struct rudp_pkt) - sizeof(struct ether_header)); hdr->hdr.uh_udp.len = htons( (sizeof(struct rudp_pkt) - sizeof(struct ether_header) - sizeof(struct iphdr)) + sent); #if 0 if ((random() % 177) == 0 && resid == 0) { hdr->hdr.uh_eth.ether_type = 0; //printf("BORK seq %u\n", ep->e.msg.ep_next_tx_seq); } #endif if (resid == 0) { hdr->msg.opcode = htons(RUDP_OP_LAST); } else { hdr->msg.opcode = htons(RUDP_OP_FIRST); } hdr->msg.m.rc_data.length = htons(sent); hdr->msg.m.rc_data.seqno = htons(ep->e.msg.ep_next_tx_seq); ++ep->e.msg.ep_next_tx_seq; wmb(); iowrite64(index, &vwq->ctrl->posted_index); wq->uwq_next_desc = (struct wq_enet_desc *) ((uintptr_t)wq->uwq_desc_ring + (index << 4)); wq->uwq_post_index = (index + 1) & wq->uwq_post_index_mask; wq->uwq_send_credits -= num_sge; } info = &wq->uwq_post_info[index]; info->wp_context = tx; info->wp_len = sge_len; /* If send complete, remove from send list */ if (resid == 0) { usdf_msg_send_complete(ep, msg); } else { msg->ms_resid = resid; msg->ms_iov_resid = cur_resid; msg->ms_cur_iov = cur_iov; msg->ms_cur_ptr = cur_ptr; } /* set ACK timer */ usdf_timer_set(ep->ep_domain->dom_fabric, ep->e.msg.ep_ack_timer, USDF_RUDP_ACK_TIMEOUT); }