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