void netfront_xmit(struct netfront_dev *dev, unsigned char* data,int len) { int flags; struct netif_tx_request *tx; RING_IDX i; int notify; unsigned short id; struct net_buffer* buf; void* page; #ifdef CONFIG_NETMAP if (dev->netmap) { netmap_netfront_xmit(dev->na, data, len); return; } #endif BUG_ON(len > PAGE_SIZE); down(&dev->tx_sem); local_irq_save(flags); id = get_id_from_freelist(dev->tx_freelist); local_irq_restore(flags); buf = &dev->tx_buffers[id]; page = buf->page; i = dev->tx.req_prod_pvt; tx = RING_GET_REQUEST(&dev->tx, i); memcpy(page,data,len); tx->gref = buf->gref; tx->offset=0; tx->size = len; tx->flags=0; tx->id = id; dev->tx.req_prod_pvt = i + 1; wmb(); RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&dev->tx, notify); if(notify) notify_remote_via_evtchn(dev->evtchn); local_irq_save(flags); network_tx_buf_gc(dev); local_irq_restore(flags); }
/** * Transmit function for raw buffers (non-GSO/TCO) */ void netfront_xmit(struct netfront_dev *dev, unsigned char *data, int len) { int flags; struct netif_tx_request *tx; struct net_txbuffer* buf; void* page; #ifdef CONFIG_NETMAP if (dev->netmap) { netmap_netfront_xmit(dev->na, data, len); return; } #endif BUG_ON(len > PAGE_SIZE); if (!netfront_tx_available(dev, 1)) goto out; tx = netfront_get_page(dev); ASSERT(tx != NULL); buf = &dev->tx_buffers[tx->id]; page = buf->page; #ifndef CONFIG_NETFRONT_PERSISTENT_GRANTS tx->gref = buf->gref = gnttab_grant_access(dev->dom, virt_to_mfn(page), 0); BUG_ON(tx->gref == GRANT_INVALID_REF); #endif NETIF_MEMCPY(page, data, len); tx->flags |= (NETTXF_data_validated); tx->size = len; #ifdef CONFIG_NETFRONT_STATS ++dev->txpkts; dev->txbytes += len; #endif netfront_xmit_notify(dev); dprintk("tx: raw %d\n", len); out: local_irq_save(flags); netfront_tx_buf_gc(dev); local_irq_restore(flags); }