xref: /qemu/hw/net/net_rx_pkt.c (revision fcf0cdc362dd96cb8d2935b892d3dd9ab73ad393)
1e263cd49SDmitry Fleytman /*
2e263cd49SDmitry Fleytman  * QEMU VMWARE VMXNET* paravirtual NICs - RX packets abstractions
3e263cd49SDmitry Fleytman  *
4e263cd49SDmitry Fleytman  * Copyright (c) 2012 Ravello Systems LTD (http://ravellosystems.com)
5e263cd49SDmitry Fleytman  *
6e263cd49SDmitry Fleytman  * Developed by Daynix Computing LTD (http://www.daynix.com)
7e263cd49SDmitry Fleytman  *
8e263cd49SDmitry Fleytman  * Authors:
9e263cd49SDmitry Fleytman  * Dmitry Fleytman <dmitry@daynix.com>
10e263cd49SDmitry Fleytman  * Tamir Shomer <tamirs@daynix.com>
11e263cd49SDmitry Fleytman  * Yan Vugenfirer <yan@daynix.com>
12e263cd49SDmitry Fleytman  *
13e263cd49SDmitry Fleytman  * This work is licensed under the terms of the GNU GPL, version 2 or later.
14e263cd49SDmitry Fleytman  * See the COPYING file in the top-level directory.
15e263cd49SDmitry Fleytman  *
16e263cd49SDmitry Fleytman  */
17e263cd49SDmitry Fleytman 
18e263cd49SDmitry Fleytman #include "vmxnet_rx_pkt.h"
19e263cd49SDmitry Fleytman #include "net/eth.h"
20e263cd49SDmitry Fleytman #include "qemu-common.h"
21e263cd49SDmitry Fleytman #include "qemu/iov.h"
22e263cd49SDmitry Fleytman #include "net/checksum.h"
23e263cd49SDmitry Fleytman #include "net/tap.h"
24e263cd49SDmitry Fleytman 
25e263cd49SDmitry Fleytman /*
26e263cd49SDmitry Fleytman  * RX packet may contain up to 2 fragments - rebuilt eth header
27e263cd49SDmitry Fleytman  * in case of VLAN tag stripping
28e263cd49SDmitry Fleytman  * and payload received from QEMU - in any case
29e263cd49SDmitry Fleytman  */
30e263cd49SDmitry Fleytman #define VMXNET_MAX_RX_PACKET_FRAGMENTS (2)
31e263cd49SDmitry Fleytman 
32e263cd49SDmitry Fleytman struct VmxnetRxPkt {
33e263cd49SDmitry Fleytman     struct virtio_net_hdr virt_hdr;
34e263cd49SDmitry Fleytman     uint8_t ehdr_buf[ETH_MAX_L2_HDR_LEN];
35e263cd49SDmitry Fleytman     struct iovec vec[VMXNET_MAX_RX_PACKET_FRAGMENTS];
36e263cd49SDmitry Fleytman     uint16_t vec_len;
37e263cd49SDmitry Fleytman     uint32_t tot_len;
38e263cd49SDmitry Fleytman     uint16_t tci;
39e263cd49SDmitry Fleytman     bool vlan_stripped;
40e263cd49SDmitry Fleytman     bool has_virt_hdr;
41e263cd49SDmitry Fleytman     eth_pkt_types_e packet_type;
42e263cd49SDmitry Fleytman 
43e263cd49SDmitry Fleytman     /* Analysis results */
44e263cd49SDmitry Fleytman     bool isip4;
45e263cd49SDmitry Fleytman     bool isip6;
46e263cd49SDmitry Fleytman     bool isudp;
47e263cd49SDmitry Fleytman     bool istcp;
48e263cd49SDmitry Fleytman };
49e263cd49SDmitry Fleytman 
50e263cd49SDmitry Fleytman void vmxnet_rx_pkt_init(struct VmxnetRxPkt **pkt, bool has_virt_hdr)
51e263cd49SDmitry Fleytman {
52e263cd49SDmitry Fleytman     struct VmxnetRxPkt *p = g_malloc0(sizeof *p);
53e263cd49SDmitry Fleytman     p->has_virt_hdr = has_virt_hdr;
54e263cd49SDmitry Fleytman     *pkt = p;
55e263cd49SDmitry Fleytman }
56e263cd49SDmitry Fleytman 
57e263cd49SDmitry Fleytman void vmxnet_rx_pkt_uninit(struct VmxnetRxPkt *pkt)
58e263cd49SDmitry Fleytman {
59e263cd49SDmitry Fleytman     g_free(pkt);
60e263cd49SDmitry Fleytman }
61e263cd49SDmitry Fleytman 
62e263cd49SDmitry Fleytman struct virtio_net_hdr *vmxnet_rx_pkt_get_vhdr(struct VmxnetRxPkt *pkt)
63e263cd49SDmitry Fleytman {
64e263cd49SDmitry Fleytman     assert(pkt);
65e263cd49SDmitry Fleytman     return &pkt->virt_hdr;
66e263cd49SDmitry Fleytman }
67e263cd49SDmitry Fleytman 
68e263cd49SDmitry Fleytman void vmxnet_rx_pkt_attach_data(struct VmxnetRxPkt *pkt, const void *data,
69e263cd49SDmitry Fleytman                                size_t len, bool strip_vlan)
70e263cd49SDmitry Fleytman {
71e263cd49SDmitry Fleytman     uint16_t tci = 0;
72e263cd49SDmitry Fleytman     uint16_t ploff;
73e263cd49SDmitry Fleytman     assert(pkt);
74e263cd49SDmitry Fleytman     pkt->vlan_stripped = false;
75e263cd49SDmitry Fleytman 
76e263cd49SDmitry Fleytman     if (strip_vlan) {
77e263cd49SDmitry Fleytman         pkt->vlan_stripped = eth_strip_vlan(data, pkt->ehdr_buf, &ploff, &tci);
78e263cd49SDmitry Fleytman     }
79e263cd49SDmitry Fleytman 
80e263cd49SDmitry Fleytman     if (pkt->vlan_stripped) {
81e263cd49SDmitry Fleytman         pkt->vec[0].iov_base = pkt->ehdr_buf;
82e263cd49SDmitry Fleytman         pkt->vec[0].iov_len = ploff - sizeof(struct vlan_header);
83e263cd49SDmitry Fleytman         pkt->vec[1].iov_base = (uint8_t *) data + ploff;
84e263cd49SDmitry Fleytman         pkt->vec[1].iov_len = len - ploff;
85e263cd49SDmitry Fleytman         pkt->vec_len = 2;
86e263cd49SDmitry Fleytman         pkt->tot_len = len - ploff + sizeof(struct eth_header);
87e263cd49SDmitry Fleytman     } else {
88e263cd49SDmitry Fleytman         pkt->vec[0].iov_base = (void *)data;
89e263cd49SDmitry Fleytman         pkt->vec[0].iov_len = len;
90e263cd49SDmitry Fleytman         pkt->vec_len = 1;
91e263cd49SDmitry Fleytman         pkt->tot_len = len;
92e263cd49SDmitry Fleytman     }
93e263cd49SDmitry Fleytman 
94e263cd49SDmitry Fleytman     pkt->tci = tci;
95e263cd49SDmitry Fleytman }
96e263cd49SDmitry Fleytman 
97e263cd49SDmitry Fleytman void vmxnet_rx_pkt_dump(struct VmxnetRxPkt *pkt)
98e263cd49SDmitry Fleytman {
99e263cd49SDmitry Fleytman #ifdef VMXNET_RX_PKT_DEBUG
100e263cd49SDmitry Fleytman     VmxnetRxPkt *pkt = (VmxnetRxPkt *)pkt;
101e263cd49SDmitry Fleytman     assert(pkt);
102e263cd49SDmitry Fleytman 
103e263cd49SDmitry Fleytman     printf("RX PKT: tot_len: %d, vlan_stripped: %d, vlan_tag: %d\n",
104e263cd49SDmitry Fleytman               pkt->tot_len, pkt->vlan_stripped, pkt->tci);
105e263cd49SDmitry Fleytman #endif
106e263cd49SDmitry Fleytman }
107e263cd49SDmitry Fleytman 
108e263cd49SDmitry Fleytman void vmxnet_rx_pkt_set_packet_type(struct VmxnetRxPkt *pkt,
109e263cd49SDmitry Fleytman     eth_pkt_types_e packet_type)
110e263cd49SDmitry Fleytman {
111e263cd49SDmitry Fleytman     assert(pkt);
112e263cd49SDmitry Fleytman 
113e263cd49SDmitry Fleytman     pkt->packet_type = packet_type;
114e263cd49SDmitry Fleytman 
115e263cd49SDmitry Fleytman }
116e263cd49SDmitry Fleytman 
117e263cd49SDmitry Fleytman eth_pkt_types_e vmxnet_rx_pkt_get_packet_type(struct VmxnetRxPkt *pkt)
118e263cd49SDmitry Fleytman {
119e263cd49SDmitry Fleytman     assert(pkt);
120e263cd49SDmitry Fleytman 
121e263cd49SDmitry Fleytman     return pkt->packet_type;
122e263cd49SDmitry Fleytman }
123e263cd49SDmitry Fleytman 
124e263cd49SDmitry Fleytman size_t vmxnet_rx_pkt_get_total_len(struct VmxnetRxPkt *pkt)
125e263cd49SDmitry Fleytman {
126e263cd49SDmitry Fleytman     assert(pkt);
127e263cd49SDmitry Fleytman 
128e263cd49SDmitry Fleytman     return pkt->tot_len;
129e263cd49SDmitry Fleytman }
130e263cd49SDmitry Fleytman 
131*fcf0cdc3SShmulik Ladkani void vmxnet_rx_pkt_set_protocols(struct VmxnetRxPkt *pkt, const void *data,
132*fcf0cdc3SShmulik Ladkani                                  size_t len)
133*fcf0cdc3SShmulik Ladkani {
134*fcf0cdc3SShmulik Ladkani     assert(pkt);
135*fcf0cdc3SShmulik Ladkani 
136*fcf0cdc3SShmulik Ladkani     eth_get_protocols(data, len, &pkt->isip4, &pkt->isip6,
137*fcf0cdc3SShmulik Ladkani         &pkt->isudp, &pkt->istcp);
138*fcf0cdc3SShmulik Ladkani }
139*fcf0cdc3SShmulik Ladkani 
140e263cd49SDmitry Fleytman void vmxnet_rx_pkt_get_protocols(struct VmxnetRxPkt *pkt,
141e263cd49SDmitry Fleytman                                  bool *isip4, bool *isip6,
142e263cd49SDmitry Fleytman                                  bool *isudp, bool *istcp)
143e263cd49SDmitry Fleytman {
144e263cd49SDmitry Fleytman     assert(pkt);
145e263cd49SDmitry Fleytman 
146e263cd49SDmitry Fleytman     *isip4 = pkt->isip4;
147e263cd49SDmitry Fleytman     *isip6 = pkt->isip6;
148e263cd49SDmitry Fleytman     *isudp = pkt->isudp;
149e263cd49SDmitry Fleytman     *istcp = pkt->istcp;
150e263cd49SDmitry Fleytman }
151e263cd49SDmitry Fleytman 
152e263cd49SDmitry Fleytman struct iovec *vmxnet_rx_pkt_get_iovec(struct VmxnetRxPkt *pkt)
153e263cd49SDmitry Fleytman {
154e263cd49SDmitry Fleytman     assert(pkt);
155e263cd49SDmitry Fleytman 
156e263cd49SDmitry Fleytman     return pkt->vec;
157e263cd49SDmitry Fleytman }
158e263cd49SDmitry Fleytman 
159e263cd49SDmitry Fleytman void vmxnet_rx_pkt_set_vhdr(struct VmxnetRxPkt *pkt,
160e263cd49SDmitry Fleytman                             struct virtio_net_hdr *vhdr)
161e263cd49SDmitry Fleytman {
162e263cd49SDmitry Fleytman     assert(pkt);
163e263cd49SDmitry Fleytman 
164e263cd49SDmitry Fleytman     memcpy(&pkt->virt_hdr, vhdr, sizeof pkt->virt_hdr);
165e263cd49SDmitry Fleytman }
166e263cd49SDmitry Fleytman 
167e263cd49SDmitry Fleytman bool vmxnet_rx_pkt_is_vlan_stripped(struct VmxnetRxPkt *pkt)
168e263cd49SDmitry Fleytman {
169e263cd49SDmitry Fleytman     assert(pkt);
170e263cd49SDmitry Fleytman 
171e263cd49SDmitry Fleytman     return pkt->vlan_stripped;
172e263cd49SDmitry Fleytman }
173e263cd49SDmitry Fleytman 
174e263cd49SDmitry Fleytman bool vmxnet_rx_pkt_has_virt_hdr(struct VmxnetRxPkt *pkt)
175e263cd49SDmitry Fleytman {
176e263cd49SDmitry Fleytman     assert(pkt);
177e263cd49SDmitry Fleytman 
178e263cd49SDmitry Fleytman     return pkt->has_virt_hdr;
179e263cd49SDmitry Fleytman }
180e263cd49SDmitry Fleytman 
181e263cd49SDmitry Fleytman uint16_t vmxnet_rx_pkt_get_vlan_tag(struct VmxnetRxPkt *pkt)
182e263cd49SDmitry Fleytman {
183e263cd49SDmitry Fleytman     assert(pkt);
184e263cd49SDmitry Fleytman 
185e263cd49SDmitry Fleytman     return pkt->tci;
186e263cd49SDmitry Fleytman }
187