Re: [PATCH net-next v21 13/13] virtio_net: Add get ethtool flow rules ops
From: "Michael S. Tsirkin" <mst@redhat.com>
Date: 2026-08-03 16:37:57
Also in:
virtualization
On Mon, Aug 03, 2026 at 05:07:21PM +0300, Shahar Shitrit wrote:
From: Daniel Jurgens <redacted> - Get total number of rules. There's no user interface for this.
For what? Isn't this ETHTOOL_GRXCLSRLCNT ?
quoted hunk ↗ jump to hunk
It is used to allocate an appropriately sized buffer for getting all the rules. - Get specific rule $ ethtool -u ens9 rule 0 Filter: 0 Rule Type: UDP over IPv4 Src IP addr: 0.0.0.0 mask: 255.255.255.255 Dest IP addr: 192.168.5.2 mask: 0.0.0.0 TOS: 0x0 mask: 0xff Src port: 0 mask: 0xffff Dest port: 4321 mask: 0x0 Action: Direct to queue 16 - Get all rules: $ ethtool -u ens9 31 RX rings available Total 2 rules Filter: 0 Rule Type: UDP over IPv4 Src IP addr: 0.0.0.0 mask: 255.255.255.255 Dest IP addr: 192.168.5.2 mask: 0.0.0.0 ... Filter: 1 Flow Type: Raw Ethernet Src MAC addr: 00:00:00:00:00:00 mask: FF:FF:FF:FF:FF:FF Dest MAC addr: 08:11:22:33:44:54 mask: 00:00:00:00:00:00 Signed-off-by: Daniel Jurgens <redacted> Reviewed-by: Parav Pandit <redacted> Reviewed-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com> Signed-off-by: Shahar Shitrit <redacted> --- drivers/net/virtio_net.c | 75 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+)diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 236887c7976d..3d5eb716361a 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c@@ -6552,6 +6552,58 @@ static int virtnet_ethtool_flow_remove(struct virtnet_ff *ff, int location) return err; } +static int virtnet_ethtool_get_flow_count(struct virtnet_ff *ff, + struct ethtool_rxnfc *info) +{ + if (!ff->ff_supported) + return -EOPNOTSUPP; + + info->rule_cnt = ff->ethtool.num_rules; + info->data = le32_to_cpu(ff->ff_caps->rules_limit) | RX_CLS_LOC_SPECIAL;
maybe check rules_per_group_limit too? they are all in 1 group ..
quoted hunk ↗ jump to hunk
+ + return 0; +} + +static int virtnet_ethtool_get_flow(struct virtnet_ff *ff, + struct ethtool_rxnfc *info) +{ + struct virtnet_ethtool_rule *eth_rule; + + if (!ff->ff_supported) + return -EOPNOTSUPP; + + eth_rule = xa_load(&ff->ethtool.rules, info->fs.location); + if (!eth_rule) + return -ENOENT; + + info->fs = eth_rule->flow_spec; + + return 0; +} + +static int +virtnet_ethtool_get_all_flows(struct virtnet_ff *ff, + struct ethtool_rxnfc *info, u32 *rule_locs) +{ + struct virtnet_ethtool_rule *eth_rule; + unsigned long i = 0; + int idx = 0; + + if (!ff->ff_supported) + return -EOPNOTSUPP; + + xa_for_each(&ff->ethtool.rules, i, eth_rule) { + if (idx == info->rule_cnt) + return -EMSGSIZE; + rule_locs[idx++] = i; + } + + info->data = le32_to_cpu(ff->ff_caps->rules_limit); + info->rule_cnt = idx; + + return 0; +} + static size_t get_mask_size(u16 type) { switch (type) {@@ -6570,6 +6622,28 @@ static size_t get_mask_size(u16 type) return 0; } +static int virtnet_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, u32 *rule_locs) +{ + struct virtnet_info *vi = netdev_priv(dev); + int rc; + + switch (info->cmd) { + case ETHTOOL_GRXCLSRLCNT: + rc = virtnet_ethtool_get_flow_count(&vi->ff, info); + break; + case ETHTOOL_GRXCLSRULE: + rc = virtnet_ethtool_get_flow(&vi->ff, info); + break; + case ETHTOOL_GRXCLSRLALL: + rc = virtnet_ethtool_get_all_flows(&vi->ff, info, rule_locs); + break; + default: + rc = -EOPNOTSUPP; + } + + return rc; +} + static int virtnet_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info) { struct virtnet_info *vi = netdev_priv(dev);@@ -6611,6 +6685,7 @@ static const struct ethtool_ops virtnet_ethtool_ops = { .get_rxfh_fields = virtnet_get_hashflow, .set_rxfh_fields = virtnet_set_hashflow, .get_rx_ring_count = virtnet_get_rx_ring_count, + .get_rxnfc = virtnet_get_rxnfc, .set_rxnfc = virtnet_set_rxnfc, };-- 2.49.0