@@ -1702,44 +1702,41 @@ static void virtio_net_hdr_swap(VirtIODevice *vdev, struct virtio_net_hdr *hdr)
17021702 * cache.
17031703 */
17041704static void work_around_broken_dhclient (struct virtio_net_hdr * hdr ,
1705- size_t * hdr_len , const uint8_t * buf ,
1706- size_t buf_size , size_t * buf_offset )
1705+ uint8_t * buf , size_t size )
17071706{
17081707 size_t csum_size = ETH_HLEN + sizeof (struct ip_header ) +
17091708 sizeof (struct udp_header );
17101709
1711- buf += * buf_offset ;
1712- buf_size -= * buf_offset ;
1713-
17141710 if ((hdr -> flags & VIRTIO_NET_HDR_F_NEEDS_CSUM ) && /* missing csum */
1715- (buf_size >= csum_size && buf_size < 1500 ) && /* normal sized MTU */
1711+ (size >= csum_size && size < 1500 ) && /* normal sized MTU */
17161712 (buf [12 ] == 0x08 && buf [13 ] == 0x00 ) && /* ethertype == IPv4 */
17171713 (buf [23 ] == 17 ) && /* ip.protocol == UDP */
17181714 (buf [34 ] == 0 && buf [35 ] == 67 )) { /* udp.srcport == bootps */
1719- memcpy ((uint8_t * )hdr + * hdr_len , buf , csum_size );
1720- net_checksum_calculate ((uint8_t * )hdr + * hdr_len , csum_size , CSUM_UDP );
1715+ net_checksum_calculate (buf , size , CSUM_UDP );
17211716 hdr -> flags &= ~VIRTIO_NET_HDR_F_NEEDS_CSUM ;
1722- * hdr_len += csum_size ;
1723- * buf_offset += csum_size ;
17241717 }
17251718}
17261719
1727- static size_t receive_header (VirtIONet * n , struct virtio_net_hdr * hdr ,
1728- const void * buf , size_t buf_size ,
1729- size_t * buf_offset )
1720+ static void receive_header (VirtIONet * n , const struct iovec * iov , int iov_cnt ,
1721+ const void * buf , size_t size )
17301722{
1731- size_t hdr_len = n -> guest_hdr_len ;
1732-
1733- memcpy (hdr , buf , sizeof (struct virtio_net_hdr ));
1734-
1735- * buf_offset = n -> host_hdr_len ;
1736- work_around_broken_dhclient (hdr , & hdr_len , buf , buf_size , buf_offset );
1723+ if (n -> has_vnet_hdr ) {
1724+ /* FIXME this cast is evil */
1725+ void * wbuf = (void * )buf ;
1726+ work_around_broken_dhclient (wbuf , wbuf + n -> host_hdr_len ,
1727+ size - n -> host_hdr_len );
17371728
1738- if (n -> needs_vnet_hdr_swap ) {
1739- virtio_net_hdr_swap (VIRTIO_DEVICE (n ), hdr );
1729+ if (n -> needs_vnet_hdr_swap ) {
1730+ virtio_net_hdr_swap (VIRTIO_DEVICE (n ), wbuf );
1731+ }
1732+ iov_from_buf (iov , iov_cnt , 0 , buf , sizeof (struct virtio_net_hdr ));
1733+ } else {
1734+ struct virtio_net_hdr hdr = {
1735+ .flags = 0 ,
1736+ .gso_type = VIRTIO_NET_HDR_GSO_NONE
1737+ };
1738+ iov_from_buf (iov , iov_cnt , 0 , & hdr , sizeof hdr );
17401739 }
1741-
1742- return hdr_len ;
17431740}
17441741
17451742static int receive_filter (VirtIONet * n , const uint8_t * buf , int size )
@@ -1907,13 +1904,6 @@ static int virtio_net_process_rss(NetClientState *nc, const uint8_t *buf,
19071904 return (index == new_index ) ? -1 : new_index ;
19081905}
19091906
1910- typedef struct Header {
1911- struct virtio_net_hdr_v1_hash virtio_net ;
1912- struct eth_header eth ;
1913- struct ip_header ip ;
1914- struct udp_header udp ;
1915- } Header ;
1916-
19171907static ssize_t virtio_net_receive_rcu (NetClientState * nc , const uint8_t * buf ,
19181908 size_t size )
19191909{
@@ -1923,15 +1913,15 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
19231913 VirtQueueElement * elems [VIRTQUEUE_MAX_SIZE ];
19241914 size_t lens [VIRTQUEUE_MAX_SIZE ];
19251915 struct iovec mhdr_sg [VIRTQUEUE_MAX_SIZE ];
1926- Header hdr ;
1916+ struct virtio_net_hdr_v1_hash extra_hdr ;
19271917 unsigned mhdr_cnt = 0 ;
19281918 size_t offset , i , guest_offset , j ;
19291919 ssize_t err ;
19301920
1931- memset (& hdr . virtio_net , 0 , sizeof (hdr . virtio_net ));
1921+ memset (& extra_hdr , 0 , sizeof (extra_hdr ));
19321922
19331923 if (n -> rss_data .enabled && n -> rss_data .enabled_software_rss ) {
1934- int index = virtio_net_process_rss (nc , buf , size , & hdr . virtio_net );
1924+ int index = virtio_net_process_rss (nc , buf , size , & extra_hdr );
19351925 if (index >= 0 ) {
19361926 nc = qemu_get_subqueue (n -> nic , index % n -> curr_queue_pairs );
19371927 }
@@ -1996,20 +1986,23 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
19961986 if (n -> mergeable_rx_bufs ) {
19971987 mhdr_cnt = iov_copy (mhdr_sg , ARRAY_SIZE (mhdr_sg ),
19981988 sg , elem -> in_num ,
1999- offsetof(typeof (hdr ),
2000- virtio_net .hdr .num_buffers ),
2001- sizeof (hdr .virtio_net .hdr .num_buffers ));
1989+ offsetof(typeof (extra_hdr ), hdr .num_buffers ),
1990+ sizeof (extra_hdr .hdr .num_buffers ));
20021991 } else {
2003- hdr . virtio_net .hdr .num_buffers = cpu_to_le16 (1 );
1992+ extra_hdr .hdr .num_buffers = cpu_to_le16 (1 );
20041993 }
20051994
2006- guest_offset = n -> has_vnet_hdr ?
2007- receive_header (n , (struct virtio_net_hdr * )& hdr ,
2008- buf , size , & offset ) :
2009- n -> guest_hdr_len ;
2010-
2011- iov_from_buf (sg , elem -> in_num , 0 , & hdr , guest_offset );
2012- total += guest_offset ;
1995+ receive_header (n , sg , elem -> in_num , buf , size );
1996+ if (n -> rss_data .populate_hash ) {
1997+ offset = offsetof(typeof (extra_hdr ), hash_value );
1998+ iov_from_buf (sg , elem -> in_num , offset ,
1999+ (char * )& extra_hdr + offset ,
2000+ sizeof (extra_hdr .hash_value ) +
2001+ sizeof (extra_hdr .hash_report ));
2002+ }
2003+ offset = n -> host_hdr_len ;
2004+ total += n -> guest_hdr_len ;
2005+ guest_offset = n -> guest_hdr_len ;
20132006 } else {
20142007 guest_offset = 0 ;
20152008 }
@@ -2035,11 +2028,11 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
20352028 }
20362029
20372030 if (mhdr_cnt ) {
2038- virtio_stw_p (vdev , & hdr . virtio_net .hdr .num_buffers , i );
2031+ virtio_stw_p (vdev , & extra_hdr .hdr .num_buffers , i );
20392032 iov_from_buf (mhdr_sg , mhdr_cnt ,
20402033 0 ,
2041- & hdr . virtio_net .hdr .num_buffers ,
2042- sizeof hdr . virtio_net .hdr .num_buffers );
2034+ & extra_hdr .hdr .num_buffers ,
2035+ sizeof extra_hdr .hdr .num_buffers );
20432036 }
20442037
20452038 for (j = 0 ; j < i ; j ++ ) {
0 commit comments