in drivers/vector_kern.c [840:905]
static int vector_legacy_rx(struct vector_private *vp)
{
int pkt_len;
struct user_msghdr hdr;
struct iovec iov[2 + MAX_IOV_SIZE]; /* header + data use case only */
int iovpos = 0;
struct sk_buff *skb;
int header_check;
hdr.msg_name = NULL;
hdr.msg_namelen = 0;
hdr.msg_iov = (struct iovec *) &iov;
hdr.msg_control = NULL;
hdr.msg_controllen = 0;
hdr.msg_flags = 0;
if (vp->header_size > 0) {
iov[0].iov_base = vp->header_rxbuffer;
iov[0].iov_len = vp->header_size;
}
skb = prep_skb(vp, &hdr);
if (skb == NULL) {
/* Read a packet into drop_buffer and don't do
* anything with it.
*/
iov[iovpos].iov_base = drop_buffer;
iov[iovpos].iov_len = DROP_BUFFER_SIZE;
hdr.msg_iovlen = 1;
vp->dev->stats.rx_dropped++;
}
pkt_len = uml_vector_recvmsg(vp->fds->rx_fd, &hdr, 0);
if (pkt_len < 0) {
vp->in_error = true;
return pkt_len;
}
if (skb != NULL) {
if (pkt_len > vp->header_size) {
if (vp->header_size > 0) {
header_check = vp->verify_header(
vp->header_rxbuffer, skb, vp);
if (header_check < 0) {
dev_kfree_skb_irq(skb);
vp->dev->stats.rx_dropped++;
vp->estats.rx_encaps_errors++;
return 0;
}
if (header_check > 0) {
vp->estats.rx_csum_offload_good++;
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
}
pskb_trim(skb, pkt_len - vp->rx_header_size);
skb->protocol = eth_type_trans(skb, skb->dev);
vp->dev->stats.rx_bytes += skb->len;
vp->dev->stats.rx_packets++;
netif_rx(skb);
} else {
dev_kfree_skb_irq(skb);
}
}
return pkt_len;
}