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