static int vector_mmsg_rx()

in drivers/vector_kern.c [958:1045]


static int vector_mmsg_rx(struct vector_private *vp)
{
	int packet_count, i;
	struct vector_queue *qi = vp->rx_queue;
	struct sk_buff *skb;
	struct mmsghdr *mmsg_vector = qi->mmsg_vector;
	void **skbuff_vector = qi->skbuff_vector;
	int header_check;

	/* Refresh the vector and make sure it is with new skbs and the
	 * iovs are updated to point to them.
	 */

	prep_queue_for_rx(qi);

	/* Fire the Lazy Gun - get as many packets as we can in one go. */

	packet_count = uml_vector_recvmmsg(
		vp->fds->rx_fd, qi->mmsg_vector, qi->max_depth, 0);

	if (packet_count < 0)
		vp->in_error = true;

	if (packet_count <= 0)
		return packet_count;

	/* We treat packet processing as enqueue, buffer refresh as dequeue
	 * The queue_depth tells us how many buffers have been used and how
	 * many do we need to prep the next time prep_queue_for_rx() is called.
	 */

	qi->queue_depth = packet_count;

	for (i = 0; i < packet_count; i++) {
		skb = (*skbuff_vector);
		if (mmsg_vector->msg_len > vp->header_size) {
			if (vp->header_size > 0) {
				header_check = vp->verify_header(
					mmsg_vector->msg_hdr.msg_iov->iov_base,
					skb,
					vp
				);
				if (header_check < 0) {
				/* Overlay header failed to verify - discard.
				 * We can actually keep this skb and reuse it,
				 * but that will make the prep logic too
				 * complex.
				 */
					dev_kfree_skb_irq(skb);
					vp->estats.rx_encaps_errors++;
					continue;
				}
				if (header_check > 0) {
					vp->estats.rx_csum_offload_good++;
					skb->ip_summed = CHECKSUM_UNNECESSARY;
				}
			}
			pskb_trim(skb,
				mmsg_vector->msg_len - vp->rx_header_size);
			skb->protocol = eth_type_trans(skb, skb->dev);
			/*
			 * We do not need to lock on updating stats here
			 * The interrupt loop is non-reentrant.
			 */
			vp->dev->stats.rx_bytes += skb->len;
			vp->dev->stats.rx_packets++;
			netif_rx(skb);
		} else {
			/* Overlay header too short to do anything - discard.
			 * We can actually keep this skb and reuse it,
			 * but that will make the prep logic too complex.
			 */
			if (skb != NULL)
				dev_kfree_skb_irq(skb);
		}
		(*skbuff_vector) = NULL;
		/* Move to the next buffer element */
		mmsg_vector++;
		skbuff_vector++;
	}
	if (packet_count > 0) {
		if (vp->estats.rx_queue_max < packet_count)
			vp->estats.rx_queue_max = packet_count;
		vp->estats.rx_queue_running_average =
			(vp->estats.rx_queue_running_average + packet_count) >> 1;
	}
	return packet_count;
}