Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
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);
}