qemu/hw/net/vmxnet_rx_pkt.c
<<
>>
Prefs
   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
  33struct 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
  51void 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
  58void vmxnet_rx_pkt_uninit(struct VmxnetRxPkt *pkt)
  59{
  60    g_free(pkt);
  61}
  62
  63struct virtio_net_hdr *vmxnet_rx_pkt_get_vhdr(struct VmxnetRxPkt *pkt)
  64{
  65    assert(pkt);
  66    return &pkt->virt_hdr;
  67}
  68
  69void 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
  98void 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
 109void 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
 118eth_pkt_types_e vmxnet_rx_pkt_get_packet_type(struct VmxnetRxPkt *pkt)
 119{
 120    assert(pkt);
 121
 122    return pkt->packet_type;
 123}
 124
 125size_t vmxnet_rx_pkt_get_total_len(struct VmxnetRxPkt *pkt)
 126{
 127    assert(pkt);
 128
 129    return pkt->tot_len;
 130}
 131
 132void 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
 141void 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
 153struct iovec *vmxnet_rx_pkt_get_iovec(struct VmxnetRxPkt *pkt)
 154{
 155    assert(pkt);
 156
 157    return pkt->vec;
 158}
 159
 160void 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
 168bool vmxnet_rx_pkt_is_vlan_stripped(struct VmxnetRxPkt *pkt)
 169{
 170    assert(pkt);
 171
 172    return pkt->vlan_stripped;
 173}
 174
 175bool vmxnet_rx_pkt_has_virt_hdr(struct VmxnetRxPkt *pkt)
 176{
 177    assert(pkt);
 178
 179    return pkt->has_virt_hdr;
 180}
 181
 182uint16_t vmxnet_rx_pkt_get_vlan_tag(struct VmxnetRxPkt *pkt)
 183{
 184    assert(pkt);
 185
 186    return pkt->tci;
 187}
 188