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