On Wed, Nov 19, 2025 at 01:15:20PM -0600, Daniel Jurgens wrote:
> Add support for IP_USER type rules from ethtool.
>
> Example:
> $ ethtool -U ens9 flow-type ip4 src-ip 192.168.51.101 action -1
> Added rule with ID 1
>
> The example rule will drop packets with the source IP specified.
>
> Signed-off-by: Daniel Jurgens <[email protected]>
> Reviewed-by: Parav Pandit <[email protected]>
> Reviewed-by: Shahar Shitrit <[email protected]>
> Reviewed-by: Xuan Zhuo <[email protected]>
> ---
> v4:
> - Fixed bug in protocol check of parse_ip4
> - (u8 *) to (void *) casting.
> - Alignment issues.
>
> v12
> - refactor calculate_flow_sizes to remove goto. MST
> - refactor build_and_insert to remove goto validate. MST
> - Move parse_ip4 l3_mask check to TCP/UDP patch. MST
> - Check saddr/daddr mask before copying in parse_ip4. MST
> - Remove tos check in setup_ip_key_mask.
So if user attempts to set a filter by tos now, what blocks it?
because parse_ip4 seems to ignore it ...
> - check l4_4_bytes mask is 0 in setup_ip_key_mask. MST
> - changed return of setup_ip_key_mask to -EINVAL.
> - BUG_ON if key overflows u8 size in calculate_flow_sizes. MST
> ---
> ---
> drivers/net/virtio_net.c | 119 +++++++++++++++++++++++++++++++++++++--
> 1 file changed, 113 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index 5e49cd78904f..b0b9972fe624 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c
> @@ -5894,6 +5894,34 @@ static bool validate_eth_mask(const struct virtnet_ff
> *ff,
> return true;
> }
>
> +static bool validate_ip4_mask(const struct virtnet_ff *ff,
> + const struct virtio_net_ff_selector *sel,
> + const struct virtio_net_ff_selector *sel_cap)
> +{
> + bool partial_mask = !!(sel_cap->flags &
> VIRTIO_NET_FF_MASK_F_PARTIAL_MASK);
> + struct iphdr *cap, *mask;
> +
> + cap = (struct iphdr *)&sel_cap->mask;
> + mask = (struct iphdr *)&sel->mask;
> +
> + if (mask->saddr &&
> + !check_mask_vs_cap(&mask->saddr, &cap->saddr,
> + sizeof(__be32), partial_mask))
> + return false;
> +
> + if (mask->daddr &&
> + !check_mask_vs_cap(&mask->daddr, &cap->daddr,
> + sizeof(__be32), partial_mask))
> + return false;
> +
> + if (mask->protocol &&
> + !check_mask_vs_cap(&mask->protocol, &cap->protocol,
> + sizeof(u8), partial_mask))
> + return false;
> +
> + return true;
> +}
> +
> static bool validate_mask(const struct virtnet_ff *ff,
> const struct virtio_net_ff_selector *sel)
> {
> @@ -5905,11 +5933,36 @@ static bool validate_mask(const struct virtnet_ff *ff,
> switch (sel->type) {
> case VIRTIO_NET_FF_MASK_TYPE_ETH:
> return validate_eth_mask(ff, sel, sel_cap);
> +
> + case VIRTIO_NET_FF_MASK_TYPE_IPV4:
> + return validate_ip4_mask(ff, sel, sel_cap);
> }
>
> return false;
> }
>
> +static void parse_ip4(struct iphdr *mask, struct iphdr *key,
> + const struct ethtool_rx_flow_spec *fs)
> +{
> + const struct ethtool_usrip4_spec *l3_mask = &fs->m_u.usr_ip4_spec;
> + const struct ethtool_usrip4_spec *l3_val = &fs->h_u.usr_ip4_spec;
> +
> + if (mask->saddr) {
> + mask->saddr = l3_mask->ip4src;
> + key->saddr = l3_val->ip4src;
> + }
So if mast->saddr is already set you over-write it?
But what sets it? Don't you really mean l3_mask->ip4src maybe?
> +
> + if (mask->daddr) {
> + mask->daddr = l3_mask->ip4dst;
> + key->daddr = l3_val->ip4dst;
> + }
> +}
Same question.