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