- Get total number of rules. There's no user interface for this. 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 <dani...@nvidia.com> Reviewed-by: Parav Pandit <pa...@nvidia.com> Reviewed-by: Shahar Shitrit <shshit...@nvidia.com> --- drivers/net/virtio_net/virtio_net_ff.c | 48 ++++++++++++++++++++++++ drivers/net/virtio_net/virtio_net_ff.h | 6 +++ drivers/net/virtio_net/virtio_net_main.c | 9 +++++ 3 files changed, 63 insertions(+) diff --git a/drivers/net/virtio_net/virtio_net_ff.c b/drivers/net/virtio_net/virtio_net_ff.c index a1f5c913bf08..2a76de5f7f32 100644 --- a/drivers/net/virtio_net/virtio_net_ff.c +++ b/drivers/net/virtio_net/virtio_net_ff.c @@ -807,6 +807,54 @@ int virtnet_ethtool_flow_remove(struct virtnet_ff *ff, int location) return err; } +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; + + return 0; +} + +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; +} + +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) + rule_locs[idx++] = i; + + info->data = le32_to_cpu(ff->ff_caps->rules_limit); + + return 0; +} + static size_t get_mask_size(u16 type) { switch (type) { diff --git a/drivers/net/virtio_net/virtio_net_ff.h b/drivers/net/virtio_net/virtio_net_ff.h index 94b575fbd9ed..4bb41e64cc59 100644 --- a/drivers/net/virtio_net/virtio_net_ff.h +++ b/drivers/net/virtio_net/virtio_net_ff.h @@ -28,6 +28,12 @@ void virtnet_ff_init(struct virtnet_ff *ff, struct virtio_device *vdev); void virtnet_ff_cleanup(struct virtnet_ff *ff); +int virtnet_ethtool_get_flow_count(struct virtnet_ff *ff, + struct ethtool_rxnfc *info); +int virtnet_ethtool_get_all_flows(struct virtnet_ff *ff, + struct ethtool_rxnfc *info, u32 *rule_locs); +int virtnet_ethtool_get_flow(struct virtnet_ff *ff, + struct ethtool_rxnfc *info); int virtnet_ethtool_flow_insert(struct virtnet_ff *ff, struct ethtool_rx_flow_spec *fs, u16 curr_queue_pairs); diff --git a/drivers/net/virtio_net/virtio_net_main.c b/drivers/net/virtio_net/virtio_net_main.c index 14ee26fc9ef3..63bf5fdc084f 100644 --- a/drivers/net/virtio_net/virtio_net_main.c +++ b/drivers/net/virtio_net/virtio_net_main.c @@ -5619,6 +5619,15 @@ static int virtnet_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, int rc = 0; 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; case ETHTOOL_GRXRINGS: info->data = vi->curr_queue_pairs; break; -- 2.50.1