mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-04 18:09:57 +00: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 */
|
||||
bool has_rss;
|
||||
bool has_rss_hash_report;
|
||||
u8 rss_key_size;
|
||||
u16 rss_indir_table_size;
|
||||
u32 rss_hash_types_supported;
|
||||
|
@ -1148,6 +1149,35 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
|
|||
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,
|
||||
void *buf, unsigned int len, void **ctx,
|
||||
unsigned int *xdp_xmit,
|
||||
|
@ -1182,6 +1212,8 @@ static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq,
|
|||
return;
|
||||
|
||||
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)
|
||||
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);
|
||||
|
||||
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");
|
||||
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,
|
||||
"VIRTIO_NET_F_CTRL_VQ") ||
|
||||
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"))) {
|
||||
return false;
|
||||
}
|
||||
|
@ -3366,8 +3401,13 @@ static int virtnet_probe(struct virtio_device *vdev)
|
|||
if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF))
|
||||
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;
|
||||
|
||||
if (vi->has_rss || vi->has_rss_hash_report) {
|
||||
vi->rss_indir_table_size =
|
||||
virtio_cread16(vdev, offsetof(struct virtio_net_config,
|
||||
rss_max_indirection_table_length));
|
||||
|
@ -3383,7 +3423,10 @@ static int virtnet_probe(struct virtio_device *vdev)
|
|||
|
||||
dev->hw_features |= NETIF_F_RXHASH;
|
||||
}
|
||||
if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF) ||
|
||||
|
||||
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);
|
||||
else
|
||||
|
@ -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);
|
||||
|
||||
err = register_netdev(dev);
|
||||
|
@ -3586,7 +3629,7 @@ static struct virtio_device_id id_table[] = {
|
|||
VIRTIO_NET_F_CTRL_MAC_ADDR, \
|
||||
VIRTIO_NET_F_MTU, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, \
|
||||
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[] = {
|
||||
VIRTNET_FEATURES,
|
||||
|
|
Loading…
Reference in a new issue