mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	drivers/net/virtio_net: Added RSS hash report.
Added features for RSS hash report. If hash is provided - it sets to skb. Added checks if rss and/or hash are enabled together. Signed-off-by: Andrew Melnychenko <andrew@daynix.com> Link: https://lore.kernel.org/r/20220328175336.10802-4-andrew@daynix.com Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
		
							parent
							
								
									c7114b1249
								
							
						
					
					
						commit
						91f41f01d2
					
				
					 1 changed files with 49 additions and 6 deletions
				
			
		| 
						 | 
					@ -227,6 +227,7 @@ struct virtnet_info {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Host supports rss and/or hash report */
 | 
						/* Host supports rss and/or hash report */
 | 
				
			||||||
	bool has_rss;
 | 
						bool has_rss;
 | 
				
			||||||
 | 
						bool has_rss_hash_report;
 | 
				
			||||||
	u8 rss_key_size;
 | 
						u8 rss_key_size;
 | 
				
			||||||
	u16 rss_indir_table_size;
 | 
						u16 rss_indir_table_size;
 | 
				
			||||||
	u32 rss_hash_types_supported;
 | 
						u32 rss_hash_types_supported;
 | 
				
			||||||
| 
						 | 
					@ -1148,6 +1149,35 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void virtio_skb_set_hash(const struct virtio_net_hdr_v1_hash *hdr_hash,
 | 
				
			||||||
 | 
									struct sk_buff *skb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						enum pkt_hash_types rss_hash_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!hdr_hash || !skb)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch ((int)hdr_hash->hash_report) {
 | 
				
			||||||
 | 
						case VIRTIO_NET_HASH_REPORT_TCPv4:
 | 
				
			||||||
 | 
						case VIRTIO_NET_HASH_REPORT_UDPv4:
 | 
				
			||||||
 | 
						case VIRTIO_NET_HASH_REPORT_TCPv6:
 | 
				
			||||||
 | 
						case VIRTIO_NET_HASH_REPORT_UDPv6:
 | 
				
			||||||
 | 
						case VIRTIO_NET_HASH_REPORT_TCPv6_EX:
 | 
				
			||||||
 | 
						case VIRTIO_NET_HASH_REPORT_UDPv6_EX:
 | 
				
			||||||
 | 
							rss_hash_type = PKT_HASH_TYPE_L4;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case VIRTIO_NET_HASH_REPORT_IPv4:
 | 
				
			||||||
 | 
						case VIRTIO_NET_HASH_REPORT_IPv6:
 | 
				
			||||||
 | 
						case VIRTIO_NET_HASH_REPORT_IPv6_EX:
 | 
				
			||||||
 | 
							rss_hash_type = PKT_HASH_TYPE_L3;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case VIRTIO_NET_HASH_REPORT_NONE:
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							rss_hash_type = PKT_HASH_TYPE_NONE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						skb_set_hash(skb, (unsigned int)hdr_hash->hash_value, rss_hash_type);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq,
 | 
					static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq,
 | 
				
			||||||
			void *buf, unsigned int len, void **ctx,
 | 
								void *buf, unsigned int len, void **ctx,
 | 
				
			||||||
			unsigned int *xdp_xmit,
 | 
								unsigned int *xdp_xmit,
 | 
				
			||||||
| 
						 | 
					@ -1182,6 +1212,8 @@ static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq,
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hdr = skb_vnet_hdr(skb);
 | 
						hdr = skb_vnet_hdr(skb);
 | 
				
			||||||
 | 
						if (dev->features & NETIF_F_RXHASH && vi->has_rss_hash_report)
 | 
				
			||||||
 | 
							virtio_skb_set_hash((const struct virtio_net_hdr_v1_hash *)hdr, skb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (hdr->hdr.flags & VIRTIO_NET_HDR_F_DATA_VALID)
 | 
						if (hdr->hdr.flags & VIRTIO_NET_HDR_F_DATA_VALID)
 | 
				
			||||||
		skb->ip_summed = CHECKSUM_UNNECESSARY;
 | 
							skb->ip_summed = CHECKSUM_UNNECESSARY;
 | 
				
			||||||
| 
						 | 
					@ -2232,7 +2264,8 @@ static bool virtnet_commit_rss_command(struct virtnet_info *vi)
 | 
				
			||||||
	sg_set_buf(&sgs[3], vi->ctrl->rss.key, sg_buf_size);
 | 
						sg_set_buf(&sgs[3], vi->ctrl->rss.key, sg_buf_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MQ,
 | 
						if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MQ,
 | 
				
			||||||
				  VIRTIO_NET_CTRL_MQ_RSS_CONFIG, sgs)) {
 | 
									  vi->has_rss ? VIRTIO_NET_CTRL_MQ_RSS_CONFIG
 | 
				
			||||||
 | 
									  : VIRTIO_NET_CTRL_MQ_HASH_CONFIG, sgs)) {
 | 
				
			||||||
		dev_warn(&dev->dev, "VIRTIONET issue with committing RSS sgs\n");
 | 
							dev_warn(&dev->dev, "VIRTIONET issue with committing RSS sgs\n");
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -3231,6 +3264,8 @@ static bool virtnet_validate_features(struct virtio_device *vdev)
 | 
				
			||||||
	     VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_CTRL_MAC_ADDR,
 | 
						     VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_CTRL_MAC_ADDR,
 | 
				
			||||||
			     "VIRTIO_NET_F_CTRL_VQ") ||
 | 
								     "VIRTIO_NET_F_CTRL_VQ") ||
 | 
				
			||||||
	     VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_RSS,
 | 
						     VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_RSS,
 | 
				
			||||||
 | 
								     "VIRTIO_NET_F_CTRL_VQ") ||
 | 
				
			||||||
 | 
						     VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_HASH_REPORT,
 | 
				
			||||||
			     "VIRTIO_NET_F_CTRL_VQ"))) {
 | 
								     "VIRTIO_NET_F_CTRL_VQ"))) {
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -3366,8 +3401,13 @@ static int virtnet_probe(struct virtio_device *vdev)
 | 
				
			||||||
	if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF))
 | 
						if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF))
 | 
				
			||||||
		vi->mergeable_rx_bufs = true;
 | 
							vi->mergeable_rx_bufs = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (virtio_has_feature(vdev, VIRTIO_NET_F_RSS)) {
 | 
						if (virtio_has_feature(vdev, VIRTIO_NET_F_HASH_REPORT))
 | 
				
			||||||
 | 
							vi->has_rss_hash_report = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (virtio_has_feature(vdev, VIRTIO_NET_F_RSS))
 | 
				
			||||||
		vi->has_rss = true;
 | 
							vi->has_rss = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (vi->has_rss || vi->has_rss_hash_report) {
 | 
				
			||||||
		vi->rss_indir_table_size =
 | 
							vi->rss_indir_table_size =
 | 
				
			||||||
			virtio_cread16(vdev, offsetof(struct virtio_net_config,
 | 
								virtio_cread16(vdev, offsetof(struct virtio_net_config,
 | 
				
			||||||
				rss_max_indirection_table_length));
 | 
									rss_max_indirection_table_length));
 | 
				
			||||||
| 
						 | 
					@ -3383,8 +3423,11 @@ static int virtnet_probe(struct virtio_device *vdev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		dev->hw_features |= NETIF_F_RXHASH;
 | 
							dev->hw_features |= NETIF_F_RXHASH;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF) ||
 | 
					
 | 
				
			||||||
	    virtio_has_feature(vdev, VIRTIO_F_VERSION_1))
 | 
						if (vi->has_rss_hash_report)
 | 
				
			||||||
 | 
							vi->hdr_len = sizeof(struct virtio_net_hdr_v1_hash);
 | 
				
			||||||
 | 
						else if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF) ||
 | 
				
			||||||
 | 
							 virtio_has_feature(vdev, VIRTIO_F_VERSION_1))
 | 
				
			||||||
		vi->hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf);
 | 
							vi->hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf);
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		vi->hdr_len = sizeof(struct virtio_net_hdr);
 | 
							vi->hdr_len = sizeof(struct virtio_net_hdr);
 | 
				
			||||||
| 
						 | 
					@ -3451,7 +3494,7 @@ static int virtnet_probe(struct virtio_device *vdev)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (vi->has_rss)
 | 
						if (vi->has_rss || vi->has_rss_hash_report)
 | 
				
			||||||
		virtnet_init_default_rss(vi);
 | 
							virtnet_init_default_rss(vi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = register_netdev(dev);
 | 
						err = register_netdev(dev);
 | 
				
			||||||
| 
						 | 
					@ -3586,7 +3629,7 @@ static struct virtio_device_id id_table[] = {
 | 
				
			||||||
	VIRTIO_NET_F_CTRL_MAC_ADDR, \
 | 
						VIRTIO_NET_F_CTRL_MAC_ADDR, \
 | 
				
			||||||
	VIRTIO_NET_F_MTU, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, \
 | 
						VIRTIO_NET_F_MTU, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, \
 | 
				
			||||||
	VIRTIO_NET_F_SPEED_DUPLEX, VIRTIO_NET_F_STANDBY, \
 | 
						VIRTIO_NET_F_SPEED_DUPLEX, VIRTIO_NET_F_STANDBY, \
 | 
				
			||||||
	VIRTIO_NET_F_RSS
 | 
						VIRTIO_NET_F_RSS, VIRTIO_NET_F_HASH_REPORT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static unsigned int features[] = {
 | 
					static unsigned int features[] = {
 | 
				
			||||||
	VIRTNET_FEATURES,
 | 
						VIRTNET_FEATURES,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue