Skip to content

Commit

Permalink
Packet abstraction for VMWARE network devices
Browse files Browse the repository at this point in the history
Signed-off-by: Dmitry Fleytman <[email protected]>
Signed-off-by: Yan Vugenfirer <[email protected]>
Signed-off-by: Stefan Hajnoczi <[email protected]>
  • Loading branch information
Dmitry Fleytman authored and stefanhaRH committed Mar 25, 2013
1 parent 75020a7 commit e263cd4
Show file tree
Hide file tree
Showing 5 changed files with 1,077 additions and 0 deletions.
1 change: 1 addition & 0 deletions hw/Makefile.objs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ common-obj-$(CONFIG_PCNET_PCI) += pcnet-pci.o
common-obj-$(CONFIG_PCNET_COMMON) += pcnet.o
common-obj-$(CONFIG_E1000_PCI) += e1000.o
common-obj-$(CONFIG_RTL8139_PCI) += rtl8139.o
common-obj-$(CONFIG_VMXNET3_PCI) += vmxnet_tx_pkt.o vmxnet_rx_pkt.o

common-obj-$(CONFIG_SMC91C111) += smc91c111.o
common-obj-$(CONFIG_LAN9118) += lan9118.o
Expand Down
187 changes: 187 additions & 0 deletions hw/vmxnet_rx_pkt.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
/*
* QEMU VMWARE VMXNET* paravirtual NICs - RX packets abstractions
*
* Copyright (c) 2012 Ravello Systems LTD (http://ravellosystems.com)
*
* Developed by Daynix Computing LTD (http://www.daynix.com)
*
* Authors:
* Dmitry Fleytman <[email protected]>
* Tamir Shomer <[email protected]>
* Yan Vugenfirer <[email protected]>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*
*/

#include "vmxnet_rx_pkt.h"
#include "net/eth.h"
#include "qemu-common.h"
#include "qemu/iov.h"
#include "net/checksum.h"
#include "net/tap.h"

/*
* RX packet may contain up to 2 fragments - rebuilt eth header
* in case of VLAN tag stripping
* and payload received from QEMU - in any case
*/
#define VMXNET_MAX_RX_PACKET_FRAGMENTS (2)

struct VmxnetRxPkt {
struct virtio_net_hdr virt_hdr;
uint8_t ehdr_buf[ETH_MAX_L2_HDR_LEN];
struct iovec vec[VMXNET_MAX_RX_PACKET_FRAGMENTS];
uint16_t vec_len;
uint32_t tot_len;
uint16_t tci;
bool vlan_stripped;
bool has_virt_hdr;
eth_pkt_types_e packet_type;

/* Analysis results */
bool isip4;
bool isip6;
bool isudp;
bool istcp;
};

void vmxnet_rx_pkt_init(struct VmxnetRxPkt **pkt, bool has_virt_hdr)
{
struct VmxnetRxPkt *p = g_malloc0(sizeof *p);
p->has_virt_hdr = has_virt_hdr;
*pkt = p;
}

void vmxnet_rx_pkt_uninit(struct VmxnetRxPkt *pkt)
{
g_free(pkt);
}

struct virtio_net_hdr *vmxnet_rx_pkt_get_vhdr(struct VmxnetRxPkt *pkt)
{
assert(pkt);
return &pkt->virt_hdr;
}

void vmxnet_rx_pkt_attach_data(struct VmxnetRxPkt *pkt, const void *data,
size_t len, bool strip_vlan)
{
uint16_t tci = 0;
uint16_t ploff;
assert(pkt);
pkt->vlan_stripped = false;

if (strip_vlan) {
pkt->vlan_stripped = eth_strip_vlan(data, pkt->ehdr_buf, &ploff, &tci);
}

if (pkt->vlan_stripped) {
pkt->vec[0].iov_base = pkt->ehdr_buf;
pkt->vec[0].iov_len = ploff - sizeof(struct vlan_header);
pkt->vec[1].iov_base = (uint8_t *) data + ploff;
pkt->vec[1].iov_len = len - ploff;
pkt->vec_len = 2;
pkt->tot_len = len - ploff + sizeof(struct eth_header);
} else {
pkt->vec[0].iov_base = (void *)data;
pkt->vec[0].iov_len = len;
pkt->vec_len = 1;
pkt->tot_len = len;
}

pkt->tci = tci;

eth_get_protocols(data, len, &pkt->isip4, &pkt->isip6,
&pkt->isudp, &pkt->istcp);
}

void vmxnet_rx_pkt_dump(struct VmxnetRxPkt *pkt)
{
#ifdef VMXNET_RX_PKT_DEBUG
VmxnetRxPkt *pkt = (VmxnetRxPkt *)pkt;
assert(pkt);

printf("RX PKT: tot_len: %d, vlan_stripped: %d, vlan_tag: %d\n",
pkt->tot_len, pkt->vlan_stripped, pkt->tci);
#endif
}

void vmxnet_rx_pkt_set_packet_type(struct VmxnetRxPkt *pkt,
eth_pkt_types_e packet_type)
{
assert(pkt);

pkt->packet_type = packet_type;

}

eth_pkt_types_e vmxnet_rx_pkt_get_packet_type(struct VmxnetRxPkt *pkt)
{
assert(pkt);

return pkt->packet_type;
}

size_t vmxnet_rx_pkt_get_total_len(struct VmxnetRxPkt *pkt)
{
assert(pkt);

return pkt->tot_len;
}

void vmxnet_rx_pkt_get_protocols(struct VmxnetRxPkt *pkt,
bool *isip4, bool *isip6,
bool *isudp, bool *istcp)
{
assert(pkt);

*isip4 = pkt->isip4;
*isip6 = pkt->isip6;
*isudp = pkt->isudp;
*istcp = pkt->istcp;
}

struct iovec *vmxnet_rx_pkt_get_iovec(struct VmxnetRxPkt *pkt)
{
assert(pkt);

return pkt->vec;
}

void vmxnet_rx_pkt_set_vhdr(struct VmxnetRxPkt *pkt,
struct virtio_net_hdr *vhdr)
{
assert(pkt);

memcpy(&pkt->virt_hdr, vhdr, sizeof pkt->virt_hdr);
}

bool vmxnet_rx_pkt_is_vlan_stripped(struct VmxnetRxPkt *pkt)
{
assert(pkt);

return pkt->vlan_stripped;
}

bool vmxnet_rx_pkt_has_virt_hdr(struct VmxnetRxPkt *pkt)
{
assert(pkt);

return pkt->has_virt_hdr;
}

uint16_t vmxnet_rx_pkt_get_num_frags(struct VmxnetRxPkt *pkt)
{
assert(pkt);

return pkt->vec_len;
}

uint16_t vmxnet_rx_pkt_get_vlan_tag(struct VmxnetRxPkt *pkt)
{
assert(pkt);

return pkt->tci;
}
174 changes: 174 additions & 0 deletions hw/vmxnet_rx_pkt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
/*
* QEMU VMWARE VMXNET* paravirtual NICs - RX packets abstraction
*
* Copyright (c) 2012 Ravello Systems LTD (http://ravellosystems.com)
*
* Developed by Daynix Computing LTD (http://www.daynix.com)
*
* Authors:
* Dmitry Fleytman <[email protected]>
* Tamir Shomer <[email protected]>
* Yan Vugenfirer <[email protected]>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*
*/

#ifndef VMXNET_RX_PKT_H
#define VMXNET_RX_PKT_H

#include "stdint.h"
#include "stdbool.h"
#include "net/eth.h"

/* defines to enable packet dump functions */
/*#define VMXNET_RX_PKT_DEBUG*/

struct VmxnetRxPkt;

/**
* Clean all rx packet resources
*
* @pkt: packet
*
*/
void vmxnet_rx_pkt_uninit(struct VmxnetRxPkt *pkt);

/**
* Init function for rx packet functionality
*
* @pkt: packet pointer
* @has_virt_hdr: device uses virtio header
*
*/
void vmxnet_rx_pkt_init(struct VmxnetRxPkt **pkt, bool has_virt_hdr);

/**
* returns total length of data attached to rx context
*
* @pkt: packet
*
* Return: nothing
*
*/
size_t vmxnet_rx_pkt_get_total_len(struct VmxnetRxPkt *pkt);

/**
* fetches packet analysis results
*
* @pkt: packet
* @isip4: whether the packet given is IPv4
* @isip6: whether the packet given is IPv6
* @isudp: whether the packet given is UDP
* @istcp: whether the packet given is TCP
*
*/
void vmxnet_rx_pkt_get_protocols(struct VmxnetRxPkt *pkt,
bool *isip4, bool *isip6,
bool *isudp, bool *istcp);

/**
* returns virtio header stored in rx context
*
* @pkt: packet
* @ret: virtio header
*
*/
struct virtio_net_hdr *vmxnet_rx_pkt_get_vhdr(struct VmxnetRxPkt *pkt);

/**
* returns packet type
*
* @pkt: packet
* @ret: packet type
*
*/
eth_pkt_types_e vmxnet_rx_pkt_get_packet_type(struct VmxnetRxPkt *pkt);

/**
* returns vlan tag
*
* @pkt: packet
* @ret: VLAN tag
*
*/
uint16_t vmxnet_rx_pkt_get_vlan_tag(struct VmxnetRxPkt *pkt);

/**
* tells whether vlan was stripped from the packet
*
* @pkt: packet
* @ret: VLAN stripped sign
*
*/
bool vmxnet_rx_pkt_is_vlan_stripped(struct VmxnetRxPkt *pkt);

/**
* notifies caller if the packet has virtio header
*
* @pkt: packet
* @ret: true if packet has virtio header, false otherwize
*
*/
bool vmxnet_rx_pkt_has_virt_hdr(struct VmxnetRxPkt *pkt);

/**
* returns number of frags attached to the packet
*
* @pkt: packet
* @ret: number of frags
*
*/
uint16_t vmxnet_rx_pkt_get_num_frags(struct VmxnetRxPkt *pkt);

/**
* attach data to rx packet
*
* @pkt: packet
* @data: pointer to the data buffer
* @len: data length
* @strip_vlan: should the module strip vlan from data
*
*/
void vmxnet_rx_pkt_attach_data(struct VmxnetRxPkt *pkt, const void *data,
size_t len, bool strip_vlan);

/**
* returns io vector that holds the attached data
*
* @pkt: packet
* @ret: pointer to IOVec
*
*/
struct iovec *vmxnet_rx_pkt_get_iovec(struct VmxnetRxPkt *pkt);

/**
* prints rx packet data if debug is enabled
*
* @pkt: packet
*
*/
void vmxnet_rx_pkt_dump(struct VmxnetRxPkt *pkt);

/**
* copy passed vhdr data to packet context
*
* @pkt: packet
* @vhdr: VHDR buffer
*
*/
void vmxnet_rx_pkt_set_vhdr(struct VmxnetRxPkt *pkt,
struct virtio_net_hdr *vhdr);

/**
* save packet type in packet context
*
* @pkt: packet
* @packet_type: the packet type
*
*/
void vmxnet_rx_pkt_set_packet_type(struct VmxnetRxPkt *pkt,
eth_pkt_types_e packet_type);

#endif
Loading

0 comments on commit e263cd4

Please sign in to comment.