mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Packet abstraction for VMWARE network devices
Signed-off-by: Dmitry Fleytman <dmitry@daynix.com> Signed-off-by: Yan Vugenfirer <yan@daynix.com> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
committed by
Stefan Hajnoczi
parent
75020a7021
commit
e263cd49c7
@@ -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
|
||||
|
||||
@@ -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 <dmitry@daynix.com>
|
||||
* Tamir Shomer <tamirs@daynix.com>
|
||||
* Yan Vugenfirer <yan@daynix.com>
|
||||
*
|
||||
* 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;
|
||||
}
|
||||
@@ -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 <dmitry@daynix.com>
|
||||
* Tamir Shomer <tamirs@daynix.com>
|
||||
* Yan Vugenfirer <yan@daynix.com>
|
||||
*
|
||||
* 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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* QEMU VMWARE VMXNET* paravirtual NICs - TX packets abstraction
|
||||
*
|
||||
* Copyright (c) 2012 Ravello Systems LTD (http://ravellosystems.com)
|
||||
*
|
||||
* Developed by Daynix Computing LTD (http://www.daynix.com)
|
||||
*
|
||||
* Authors:
|
||||
* Dmitry Fleytman <dmitry@daynix.com>
|
||||
* Tamir Shomer <tamirs@daynix.com>
|
||||
* Yan Vugenfirer <yan@daynix.com>
|
||||
*
|
||||
* 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_TX_PKT_H
|
||||
#define VMXNET_TX_PKT_H
|
||||
|
||||
#include "stdint.h"
|
||||
#include "stdbool.h"
|
||||
#include "net/eth.h"
|
||||
#include "exec/hwaddr.h"
|
||||
|
||||
/* define to enable packet dump functions */
|
||||
/*#define VMXNET_TX_PKT_DEBUG*/
|
||||
|
||||
struct VmxnetTxPkt;
|
||||
|
||||
/**
|
||||
* Init function for tx packet functionality
|
||||
*
|
||||
* @pkt: packet pointer
|
||||
* @max_frags: max tx ip fragments
|
||||
* @has_virt_hdr: device uses virtio header.
|
||||
*/
|
||||
void vmxnet_tx_pkt_init(struct VmxnetTxPkt **pkt, uint32_t max_frags,
|
||||
bool has_virt_hdr);
|
||||
|
||||
/**
|
||||
* Clean all tx packet resources.
|
||||
*
|
||||
* @pkt: packet.
|
||||
*/
|
||||
void vmxnet_tx_pkt_uninit(struct VmxnetTxPkt *pkt);
|
||||
|
||||
/**
|
||||
* get virtio header
|
||||
*
|
||||
* @pkt: packet
|
||||
* @ret: virtio header
|
||||
*/
|
||||
struct virtio_net_hdr *vmxnet_tx_pkt_get_vhdr(struct VmxnetTxPkt *pkt);
|
||||
|
||||
/**
|
||||
* build virtio header (will be stored in module context)
|
||||
*
|
||||
* @pkt: packet
|
||||
* @tso_enable: TSO enabled
|
||||
* @csum_enable: CSO enabled
|
||||
* @gso_size: MSS size for TSO
|
||||
*
|
||||
*/
|
||||
void vmxnet_tx_pkt_build_vheader(struct VmxnetTxPkt *pkt, bool tso_enable,
|
||||
bool csum_enable, uint32_t gso_size);
|
||||
|
||||
/**
|
||||
* updates vlan tag, and adds vlan header in case it is missing
|
||||
*
|
||||
* @pkt: packet
|
||||
* @vlan: VLAN tag
|
||||
*
|
||||
*/
|
||||
void vmxnet_tx_pkt_setup_vlan_header(struct VmxnetTxPkt *pkt, uint16_t vlan);
|
||||
|
||||
/**
|
||||
* populate data fragment into pkt context.
|
||||
*
|
||||
* @pkt: packet
|
||||
* @pa: physical address of fragment
|
||||
* @len: length of fragment
|
||||
*
|
||||
*/
|
||||
bool vmxnet_tx_pkt_add_raw_fragment(struct VmxnetTxPkt *pkt, hwaddr pa,
|
||||
size_t len);
|
||||
|
||||
/**
|
||||
* fix ip header fields and calculate checksums needed.
|
||||
*
|
||||
* @pkt: packet
|
||||
*
|
||||
*/
|
||||
void vmxnet_tx_pkt_update_ip_checksums(struct VmxnetTxPkt *pkt);
|
||||
|
||||
/**
|
||||
* get length of all populated data.
|
||||
*
|
||||
* @pkt: packet
|
||||
* @ret: total data length
|
||||
*
|
||||
*/
|
||||
size_t vmxnet_tx_pkt_get_total_len(struct VmxnetTxPkt *pkt);
|
||||
|
||||
/**
|
||||
* get packet type
|
||||
*
|
||||
* @pkt: packet
|
||||
* @ret: packet type
|
||||
*
|
||||
*/
|
||||
eth_pkt_types_e vmxnet_tx_pkt_get_packet_type(struct VmxnetTxPkt *pkt);
|
||||
|
||||
/**
|
||||
* prints packet data if debug is enabled
|
||||
*
|
||||
* @pkt: packet
|
||||
*
|
||||
*/
|
||||
void vmxnet_tx_pkt_dump(struct VmxnetTxPkt *pkt);
|
||||
|
||||
/**
|
||||
* reset tx packet private context (needed to be called between packets)
|
||||
*
|
||||
* @pkt: packet
|
||||
*
|
||||
*/
|
||||
void vmxnet_tx_pkt_reset(struct VmxnetTxPkt *pkt);
|
||||
|
||||
/**
|
||||
* Send packet to qemu. handles sw offloads if vhdr is not supported.
|
||||
*
|
||||
* @pkt: packet
|
||||
* @nc: NetClientState
|
||||
* @ret: operation result
|
||||
*
|
||||
*/
|
||||
bool vmxnet_tx_pkt_send(struct VmxnetTxPkt *pkt, NetClientState *nc);
|
||||
|
||||
/**
|
||||
* parse raw packet data and analyze offload requirements.
|
||||
*
|
||||
* @pkt: packet
|
||||
*
|
||||
*/
|
||||
bool vmxnet_tx_pkt_parse(struct VmxnetTxPkt *pkt);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user