Skip to content

Commit 86a48a0

Browse files
LPhghPaolo Abeni
authored andcommitted
virtio_net: Support dynamic rss indirection table size
When reading/writing virtio_net_ctrl_rss, we get the indirection table size from vi->rss_indir_table_size, which is initialized in virtnet_probe(). However, the actual size of indirection_table was set as VIRTIO_NET_RSS_MAX_TABLE_LEN=128. This collision may cause issues if the vi->rss_indir_table_size exceeds 128. This patch instead uses dynamic indirection table, allocated with vi->rss after vi->rss_indir_table_size initialized. And free it in virtnet_remove(). In virtnet_commit_rss_command(), sgs for rss is initialized differently with hash_report. So indirection_table is not used if !vi->has_rss, and then we don't need to alloc indirection_table for hash_report only uses. Fixes: c7114b1 ("drivers/net/virtio_net: Added basic RSS support.") Signed-off-by: Philo Lu <[email protected]> Signed-off-by: Xuan Zhuo <[email protected]> Acked-by: Joe Damato <[email protected]> Acked-by: Michael S. Tsirkin <[email protected]> Signed-off-by: Paolo Abeni <[email protected]>
1 parent 25d7070 commit 86a48a0

File tree

1 file changed

+34
-5
lines changed

1 file changed

+34
-5
lines changed

drivers/net/virtio_net.c

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -368,15 +368,16 @@ struct receive_queue {
368368
* because table sizes may be differ according to the device configuration.
369369
*/
370370
#define VIRTIO_NET_RSS_MAX_KEY_SIZE 40
371-
#define VIRTIO_NET_RSS_MAX_TABLE_LEN 128
372371
struct virtio_net_ctrl_rss {
373372
u32 hash_types;
374373
u16 indirection_table_mask;
375374
u16 unclassified_queue;
376-
u16 indirection_table[VIRTIO_NET_RSS_MAX_TABLE_LEN];
375+
u16 hash_cfg_reserved; /* for HASH_CONFIG (see virtio_net_hash_config for details) */
377376
u16 max_tx_vq;
378377
u8 hash_key_length;
379378
u8 key[VIRTIO_NET_RSS_MAX_KEY_SIZE];
379+
380+
u16 *indirection_table;
380381
};
381382

382383
/* Control VQ buffers: protected by the rtnl lock */
@@ -512,6 +513,25 @@ static struct sk_buff *virtnet_skb_append_frag(struct sk_buff *head_skb,
512513
struct page *page, void *buf,
513514
int len, int truesize);
514515

516+
static int rss_indirection_table_alloc(struct virtio_net_ctrl_rss *rss, u16 indir_table_size)
517+
{
518+
if (!indir_table_size) {
519+
rss->indirection_table = NULL;
520+
return 0;
521+
}
522+
523+
rss->indirection_table = kmalloc_array(indir_table_size, sizeof(u16), GFP_KERNEL);
524+
if (!rss->indirection_table)
525+
return -ENOMEM;
526+
527+
return 0;
528+
}
529+
530+
static void rss_indirection_table_free(struct virtio_net_ctrl_rss *rss)
531+
{
532+
kfree(rss->indirection_table);
533+
}
534+
515535
static bool is_xdp_frame(void *ptr)
516536
{
517537
return (unsigned long)ptr & VIRTIO_XDP_FLAG;
@@ -3828,11 +3848,15 @@ static bool virtnet_commit_rss_command(struct virtnet_info *vi)
38283848
/* prepare sgs */
38293849
sg_init_table(sgs, 4);
38303850

3831-
sg_buf_size = offsetof(struct virtio_net_ctrl_rss, indirection_table);
3851+
sg_buf_size = offsetof(struct virtio_net_ctrl_rss, hash_cfg_reserved);
38323852
sg_set_buf(&sgs[0], &vi->rss, sg_buf_size);
38333853

3834-
sg_buf_size = sizeof(uint16_t) * (vi->rss.indirection_table_mask + 1);
3835-
sg_set_buf(&sgs[1], vi->rss.indirection_table, sg_buf_size);
3854+
if (vi->has_rss) {
3855+
sg_buf_size = sizeof(uint16_t) * vi->rss_indir_table_size;
3856+
sg_set_buf(&sgs[1], vi->rss.indirection_table, sg_buf_size);
3857+
} else {
3858+
sg_set_buf(&sgs[1], &vi->rss.hash_cfg_reserved, sizeof(uint16_t));
3859+
}
38363860

38373861
sg_buf_size = offsetof(struct virtio_net_ctrl_rss, key)
38383862
- offsetof(struct virtio_net_ctrl_rss, max_tx_vq);
@@ -6420,6 +6444,9 @@ static int virtnet_probe(struct virtio_device *vdev)
64206444
virtio_cread16(vdev, offsetof(struct virtio_net_config,
64216445
rss_max_indirection_table_length));
64226446
}
6447+
err = rss_indirection_table_alloc(&vi->rss, vi->rss_indir_table_size);
6448+
if (err)
6449+
goto free;
64236450

64246451
if (vi->has_rss || vi->has_rss_hash_report) {
64256452
vi->rss_key_size =
@@ -6674,6 +6701,8 @@ static void virtnet_remove(struct virtio_device *vdev)
66746701

66756702
remove_vq_common(vi);
66766703

6704+
rss_indirection_table_free(&vi->rss);
6705+
66776706
free_netdev(vi->dev);
66786707
}
66796708

0 commit comments

Comments
 (0)