1e263cd49SDmitry Fleytman /* 2e263cd49SDmitry Fleytman * QEMU VMWARE VMXNET* paravirtual NICs - RX packets abstractions 3e263cd49SDmitry Fleytman * 4e263cd49SDmitry Fleytman * Copyright (c) 2012 Ravello Systems LTD (http://ravellosystems.com) 5e263cd49SDmitry Fleytman * 6e263cd49SDmitry Fleytman * Developed by Daynix Computing LTD (http://www.daynix.com) 7e263cd49SDmitry Fleytman * 8e263cd49SDmitry Fleytman * Authors: 9e263cd49SDmitry Fleytman * Dmitry Fleytman <dmitry@daynix.com> 10e263cd49SDmitry Fleytman * Tamir Shomer <tamirs@daynix.com> 11e263cd49SDmitry Fleytman * Yan Vugenfirer <yan@daynix.com> 12e263cd49SDmitry Fleytman * 13e263cd49SDmitry Fleytman * This work is licensed under the terms of the GNU GPL, version 2 or later. 14e263cd49SDmitry Fleytman * See the COPYING file in the top-level directory. 15e263cd49SDmitry Fleytman * 16e263cd49SDmitry Fleytman */ 17e263cd49SDmitry Fleytman 18e263cd49SDmitry Fleytman #include "vmxnet_rx_pkt.h" 19e263cd49SDmitry Fleytman #include "net/eth.h" 20e263cd49SDmitry Fleytman #include "qemu-common.h" 21e263cd49SDmitry Fleytman #include "qemu/iov.h" 22e263cd49SDmitry Fleytman #include "net/checksum.h" 23e263cd49SDmitry Fleytman #include "net/tap.h" 24e263cd49SDmitry Fleytman 25e263cd49SDmitry Fleytman /* 26e263cd49SDmitry Fleytman * RX packet may contain up to 2 fragments - rebuilt eth header 27e263cd49SDmitry Fleytman * in case of VLAN tag stripping 28e263cd49SDmitry Fleytman * and payload received from QEMU - in any case 29e263cd49SDmitry Fleytman */ 30e263cd49SDmitry Fleytman #define VMXNET_MAX_RX_PACKET_FRAGMENTS (2) 31e263cd49SDmitry Fleytman 32e263cd49SDmitry Fleytman struct VmxnetRxPkt { 33e263cd49SDmitry Fleytman struct virtio_net_hdr virt_hdr; 34e263cd49SDmitry Fleytman uint8_t ehdr_buf[ETH_MAX_L2_HDR_LEN]; 35e263cd49SDmitry Fleytman struct iovec vec[VMXNET_MAX_RX_PACKET_FRAGMENTS]; 36e263cd49SDmitry Fleytman uint16_t vec_len; 37e263cd49SDmitry Fleytman uint32_t tot_len; 38e263cd49SDmitry Fleytman uint16_t tci; 39e263cd49SDmitry Fleytman bool vlan_stripped; 40e263cd49SDmitry Fleytman bool has_virt_hdr; 41e263cd49SDmitry Fleytman eth_pkt_types_e packet_type; 42e263cd49SDmitry Fleytman 43e263cd49SDmitry Fleytman /* Analysis results */ 44e263cd49SDmitry Fleytman bool isip4; 45e263cd49SDmitry Fleytman bool isip6; 46e263cd49SDmitry Fleytman bool isudp; 47e263cd49SDmitry Fleytman bool istcp; 48e263cd49SDmitry Fleytman }; 49e263cd49SDmitry Fleytman 50e263cd49SDmitry Fleytman void vmxnet_rx_pkt_init(struct VmxnetRxPkt **pkt, bool has_virt_hdr) 51e263cd49SDmitry Fleytman { 52e263cd49SDmitry Fleytman struct VmxnetRxPkt *p = g_malloc0(sizeof *p); 53e263cd49SDmitry Fleytman p->has_virt_hdr = has_virt_hdr; 54e263cd49SDmitry Fleytman *pkt = p; 55e263cd49SDmitry Fleytman } 56e263cd49SDmitry Fleytman 57e263cd49SDmitry Fleytman void vmxnet_rx_pkt_uninit(struct VmxnetRxPkt *pkt) 58e263cd49SDmitry Fleytman { 59e263cd49SDmitry Fleytman g_free(pkt); 60e263cd49SDmitry Fleytman } 61e263cd49SDmitry Fleytman 62e263cd49SDmitry Fleytman struct virtio_net_hdr *vmxnet_rx_pkt_get_vhdr(struct VmxnetRxPkt *pkt) 63e263cd49SDmitry Fleytman { 64e263cd49SDmitry Fleytman assert(pkt); 65e263cd49SDmitry Fleytman return &pkt->virt_hdr; 66e263cd49SDmitry Fleytman } 67e263cd49SDmitry Fleytman 68e263cd49SDmitry Fleytman void vmxnet_rx_pkt_attach_data(struct VmxnetRxPkt *pkt, const void *data, 69e263cd49SDmitry Fleytman size_t len, bool strip_vlan) 70e263cd49SDmitry Fleytman { 71e263cd49SDmitry Fleytman uint16_t tci = 0; 72e263cd49SDmitry Fleytman uint16_t ploff; 73e263cd49SDmitry Fleytman assert(pkt); 74e263cd49SDmitry Fleytman pkt->vlan_stripped = false; 75e263cd49SDmitry Fleytman 76e263cd49SDmitry Fleytman if (strip_vlan) { 77e263cd49SDmitry Fleytman pkt->vlan_stripped = eth_strip_vlan(data, pkt->ehdr_buf, &ploff, &tci); 78e263cd49SDmitry Fleytman } 79e263cd49SDmitry Fleytman 80e263cd49SDmitry Fleytman if (pkt->vlan_stripped) { 81e263cd49SDmitry Fleytman pkt->vec[0].iov_base = pkt->ehdr_buf; 82e263cd49SDmitry Fleytman pkt->vec[0].iov_len = ploff - sizeof(struct vlan_header); 83e263cd49SDmitry Fleytman pkt->vec[1].iov_base = (uint8_t *) data + ploff; 84e263cd49SDmitry Fleytman pkt->vec[1].iov_len = len - ploff; 85e263cd49SDmitry Fleytman pkt->vec_len = 2; 86e263cd49SDmitry Fleytman pkt->tot_len = len - ploff + sizeof(struct eth_header); 87e263cd49SDmitry Fleytman } else { 88e263cd49SDmitry Fleytman pkt->vec[0].iov_base = (void *)data; 89e263cd49SDmitry Fleytman pkt->vec[0].iov_len = len; 90e263cd49SDmitry Fleytman pkt->vec_len = 1; 91e263cd49SDmitry Fleytman pkt->tot_len = len; 92e263cd49SDmitry Fleytman } 93e263cd49SDmitry Fleytman 94e263cd49SDmitry Fleytman pkt->tci = tci; 95e263cd49SDmitry Fleytman } 96e263cd49SDmitry Fleytman 97e263cd49SDmitry Fleytman void vmxnet_rx_pkt_dump(struct VmxnetRxPkt *pkt) 98e263cd49SDmitry Fleytman { 99e263cd49SDmitry Fleytman #ifdef VMXNET_RX_PKT_DEBUG 100e263cd49SDmitry Fleytman VmxnetRxPkt *pkt = (VmxnetRxPkt *)pkt; 101e263cd49SDmitry Fleytman assert(pkt); 102e263cd49SDmitry Fleytman 103e263cd49SDmitry Fleytman printf("RX PKT: tot_len: %d, vlan_stripped: %d, vlan_tag: %d\n", 104e263cd49SDmitry Fleytman pkt->tot_len, pkt->vlan_stripped, pkt->tci); 105e263cd49SDmitry Fleytman #endif 106e263cd49SDmitry Fleytman } 107e263cd49SDmitry Fleytman 108e263cd49SDmitry Fleytman void vmxnet_rx_pkt_set_packet_type(struct VmxnetRxPkt *pkt, 109e263cd49SDmitry Fleytman eth_pkt_types_e packet_type) 110e263cd49SDmitry Fleytman { 111e263cd49SDmitry Fleytman assert(pkt); 112e263cd49SDmitry Fleytman 113e263cd49SDmitry Fleytman pkt->packet_type = packet_type; 114e263cd49SDmitry Fleytman 115e263cd49SDmitry Fleytman } 116e263cd49SDmitry Fleytman 117e263cd49SDmitry Fleytman eth_pkt_types_e vmxnet_rx_pkt_get_packet_type(struct VmxnetRxPkt *pkt) 118e263cd49SDmitry Fleytman { 119e263cd49SDmitry Fleytman assert(pkt); 120e263cd49SDmitry Fleytman 121e263cd49SDmitry Fleytman return pkt->packet_type; 122e263cd49SDmitry Fleytman } 123e263cd49SDmitry Fleytman 124e263cd49SDmitry Fleytman size_t vmxnet_rx_pkt_get_total_len(struct VmxnetRxPkt *pkt) 125e263cd49SDmitry Fleytman { 126e263cd49SDmitry Fleytman assert(pkt); 127e263cd49SDmitry Fleytman 128e263cd49SDmitry Fleytman return pkt->tot_len; 129e263cd49SDmitry Fleytman } 130e263cd49SDmitry Fleytman 131*fcf0cdc3SShmulik Ladkani void vmxnet_rx_pkt_set_protocols(struct VmxnetRxPkt *pkt, const void *data, 132*fcf0cdc3SShmulik Ladkani size_t len) 133*fcf0cdc3SShmulik Ladkani { 134*fcf0cdc3SShmulik Ladkani assert(pkt); 135*fcf0cdc3SShmulik Ladkani 136*fcf0cdc3SShmulik Ladkani eth_get_protocols(data, len, &pkt->isip4, &pkt->isip6, 137*fcf0cdc3SShmulik Ladkani &pkt->isudp, &pkt->istcp); 138*fcf0cdc3SShmulik Ladkani } 139*fcf0cdc3SShmulik Ladkani 140e263cd49SDmitry Fleytman void vmxnet_rx_pkt_get_protocols(struct VmxnetRxPkt *pkt, 141e263cd49SDmitry Fleytman bool *isip4, bool *isip6, 142e263cd49SDmitry Fleytman bool *isudp, bool *istcp) 143e263cd49SDmitry Fleytman { 144e263cd49SDmitry Fleytman assert(pkt); 145e263cd49SDmitry Fleytman 146e263cd49SDmitry Fleytman *isip4 = pkt->isip4; 147e263cd49SDmitry Fleytman *isip6 = pkt->isip6; 148e263cd49SDmitry Fleytman *isudp = pkt->isudp; 149e263cd49SDmitry Fleytman *istcp = pkt->istcp; 150e263cd49SDmitry Fleytman } 151e263cd49SDmitry Fleytman 152e263cd49SDmitry Fleytman struct iovec *vmxnet_rx_pkt_get_iovec(struct VmxnetRxPkt *pkt) 153e263cd49SDmitry Fleytman { 154e263cd49SDmitry Fleytman assert(pkt); 155e263cd49SDmitry Fleytman 156e263cd49SDmitry Fleytman return pkt->vec; 157e263cd49SDmitry Fleytman } 158e263cd49SDmitry Fleytman 159e263cd49SDmitry Fleytman void vmxnet_rx_pkt_set_vhdr(struct VmxnetRxPkt *pkt, 160e263cd49SDmitry Fleytman struct virtio_net_hdr *vhdr) 161e263cd49SDmitry Fleytman { 162e263cd49SDmitry Fleytman assert(pkt); 163e263cd49SDmitry Fleytman 164e263cd49SDmitry Fleytman memcpy(&pkt->virt_hdr, vhdr, sizeof pkt->virt_hdr); 165e263cd49SDmitry Fleytman } 166e263cd49SDmitry Fleytman 167e263cd49SDmitry Fleytman bool vmxnet_rx_pkt_is_vlan_stripped(struct VmxnetRxPkt *pkt) 168e263cd49SDmitry Fleytman { 169e263cd49SDmitry Fleytman assert(pkt); 170e263cd49SDmitry Fleytman 171e263cd49SDmitry Fleytman return pkt->vlan_stripped; 172e263cd49SDmitry Fleytman } 173e263cd49SDmitry Fleytman 174e263cd49SDmitry Fleytman bool vmxnet_rx_pkt_has_virt_hdr(struct VmxnetRxPkt *pkt) 175e263cd49SDmitry Fleytman { 176e263cd49SDmitry Fleytman assert(pkt); 177e263cd49SDmitry Fleytman 178e263cd49SDmitry Fleytman return pkt->has_virt_hdr; 179e263cd49SDmitry Fleytman } 180e263cd49SDmitry Fleytman 181e263cd49SDmitry Fleytman uint16_t vmxnet_rx_pkt_get_vlan_tag(struct VmxnetRxPkt *pkt) 182e263cd49SDmitry Fleytman { 183e263cd49SDmitry Fleytman assert(pkt); 184e263cd49SDmitry Fleytman 185e263cd49SDmitry Fleytman return pkt->tci; 186e263cd49SDmitry Fleytman } 187