These changes are the raw update to qemu-2.6.
[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 "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  * RX packet may contain up to 2 fragments - rebuilt eth header
28  * in case of VLAN tag stripping
29  * and payload received from QEMU - in any case
30  */
31 #define VMXNET_MAX_RX_PACKET_FRAGMENTS (2)
32
33 struct 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     /* Analysis results */
45     bool isip4;
46     bool isip6;
47     bool isudp;
48     bool istcp;
49 };
50
51 void 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
58 void vmxnet_rx_pkt_uninit(struct VmxnetRxPkt *pkt)
59 {
60     g_free(pkt);
61 }
62
63 struct virtio_net_hdr *vmxnet_rx_pkt_get_vhdr(struct VmxnetRxPkt *pkt)
64 {
65     assert(pkt);
66     return &pkt->virt_hdr;
67 }
68
69 void 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
98 void 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
109 void 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
118 eth_pkt_types_e vmxnet_rx_pkt_get_packet_type(struct VmxnetRxPkt *pkt)
119 {
120     assert(pkt);
121
122     return pkt->packet_type;
123 }
124
125 size_t vmxnet_rx_pkt_get_total_len(struct VmxnetRxPkt *pkt)
126 {
127     assert(pkt);
128
129     return pkt->tot_len;
130 }
131
132 void 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
141 void 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
153 struct iovec *vmxnet_rx_pkt_get_iovec(struct VmxnetRxPkt *pkt)
154 {
155     assert(pkt);
156
157     return pkt->vec;
158 }
159
160 void 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
168 bool vmxnet_rx_pkt_is_vlan_stripped(struct VmxnetRxPkt *pkt)
169 {
170     assert(pkt);
171
172     return pkt->vlan_stripped;
173 }
174
175 bool vmxnet_rx_pkt_has_virt_hdr(struct VmxnetRxPkt *pkt)
176 {
177     assert(pkt);
178
179     return pkt->has_virt_hdr;
180 }
181
182 uint16_t vmxnet_rx_pkt_get_vlan_tag(struct VmxnetRxPkt *pkt)
183 {
184     assert(pkt);
185
186     return pkt->tci;
187 }