Add qemu 2.4.0
[kvmfornfv.git] / qemu / hw / net / vmxnet_rx_pkt.c
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
97 void vmxnet_rx_pkt_dump(struct VmxnetRxPkt *pkt)
98 {
99 #ifdef VMXNET_RX_PKT_DEBUG
100     VmxnetRxPkt *pkt = (VmxnetRxPkt *)pkt;
101     assert(pkt);
102
103     printf("RX PKT: tot_len: %d, vlan_stripped: %d, vlan_tag: %d\n",
104               pkt->tot_len, pkt->vlan_stripped, pkt->tci);
105 #endif
106 }
107
108 void vmxnet_rx_pkt_set_packet_type(struct VmxnetRxPkt *pkt,
109     eth_pkt_types_e packet_type)
110 {
111     assert(pkt);
112
113     pkt->packet_type = packet_type;
114
115 }
116
117 eth_pkt_types_e vmxnet_rx_pkt_get_packet_type(struct VmxnetRxPkt *pkt)
118 {
119     assert(pkt);
120
121     return pkt->packet_type;
122 }
123
124 size_t vmxnet_rx_pkt_get_total_len(struct VmxnetRxPkt *pkt)
125 {
126     assert(pkt);
127
128     return pkt->tot_len;
129 }
130
131 void vmxnet_rx_pkt_set_protocols(struct VmxnetRxPkt *pkt, const void *data,
132                                  size_t len)
133 {
134     assert(pkt);
135
136     eth_get_protocols(data, len, &pkt->isip4, &pkt->isip6,
137         &pkt->isudp, &pkt->istcp);
138 }
139
140 void vmxnet_rx_pkt_get_protocols(struct VmxnetRxPkt *pkt,
141                                  bool *isip4, bool *isip6,
142                                  bool *isudp, bool *istcp)
143 {
144     assert(pkt);
145
146     *isip4 = pkt->isip4;
147     *isip6 = pkt->isip6;
148     *isudp = pkt->isudp;
149     *istcp = pkt->istcp;
150 }
151
152 struct iovec *vmxnet_rx_pkt_get_iovec(struct VmxnetRxPkt *pkt)
153 {
154     assert(pkt);
155
156     return pkt->vec;
157 }
158
159 void vmxnet_rx_pkt_set_vhdr(struct VmxnetRxPkt *pkt,
160                             struct virtio_net_hdr *vhdr)
161 {
162     assert(pkt);
163
164     memcpy(&pkt->virt_hdr, vhdr, sizeof pkt->virt_hdr);
165 }
166
167 bool vmxnet_rx_pkt_is_vlan_stripped(struct VmxnetRxPkt *pkt)
168 {
169     assert(pkt);
170
171     return pkt->vlan_stripped;
172 }
173
174 bool vmxnet_rx_pkt_has_virt_hdr(struct VmxnetRxPkt *pkt)
175 {
176     assert(pkt);
177
178     return pkt->has_virt_hdr;
179 }
180
181 uint16_t vmxnet_rx_pkt_get_vlan_tag(struct VmxnetRxPkt *pkt)
182 {
183     assert(pkt);
184
185     return pkt->tci;
186 }