1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
28
29
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
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