Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit be2902da authored by Ben Hutchings's avatar Ben Hutchings Committed by David S. Miller
Browse files

ethtool, ixgbe: Move RX n-tuple mask fixup to ethtool



The ethtool utility does not set masks for flow parameters that are
not specified, so if both value and mask are 0 then this must be
treated as equivalent to a mask with all bits set.  Currently that is
done in the only driver that implements RX n-tuple filtering, ixgbe.
Move it to the ethtool core.

Signed-off-by: default avatarBen Hutchings <bhutchings@solarflare.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3b27e105
Loading
Loading
Loading
Loading
+14 −43
Original line number Original line Diff line number Diff line
@@ -1910,53 +1910,24 @@ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
	              (dst_port << IXGBE_FDIRPORT_DESTINATION_SHIFT)));
	              (dst_port << IXGBE_FDIRPORT_DESTINATION_SHIFT)));


	/*
	/*
	 * Program the relevant mask registers.  If src/dst_port or src/dst_addr
	 * Program the relevant mask registers.  L4type cannot be
	 * are zero, then assume a full mask for that field.  Also assume that
	 * masked out in this implementation.
	 * a VLAN of 0 is unspecified, so mask that out as well.  L4type
	 * cannot be masked out in this implementation.
	 *
	 *
	 * This also assumes IPv4 only.  IPv6 masking isn't supported at this
	 * This also assumes IPv4 only.  IPv6 masking isn't supported at this
	 * point in time.
	 * point in time.
	 */
	 */
	if (src_ipv4 == 0)
		IXGBE_WRITE_REG(hw, IXGBE_FDIRSIP4M, 0xffffffff);
	else
	IXGBE_WRITE_REG(hw, IXGBE_FDIRSIP4M, input_masks->src_ip_mask);
	IXGBE_WRITE_REG(hw, IXGBE_FDIRSIP4M, input_masks->src_ip_mask);

	if (dst_ipv4 == 0)
		IXGBE_WRITE_REG(hw, IXGBE_FDIRDIP4M, 0xffffffff);
	else
	IXGBE_WRITE_REG(hw, IXGBE_FDIRDIP4M, input_masks->dst_ip_mask);
	IXGBE_WRITE_REG(hw, IXGBE_FDIRDIP4M, input_masks->dst_ip_mask);


	switch (l4type & IXGBE_ATR_L4TYPE_MASK) {
	switch (l4type & IXGBE_ATR_L4TYPE_MASK) {
	case IXGBE_ATR_L4TYPE_TCP:
	case IXGBE_ATR_L4TYPE_TCP:
		if (src_port == 0)
		IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, input_masks->src_port_mask);
			IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, 0xffff);
		else
			IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM,
			                input_masks->src_port_mask);

		if (dst_port == 0)
			IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM,
			               (IXGBE_READ_REG(hw, IXGBE_FDIRTCPM) |
			                (0xffff << 16)));
		else
		IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM,
		IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM,
				(IXGBE_READ_REG(hw, IXGBE_FDIRTCPM) |
				(IXGBE_READ_REG(hw, IXGBE_FDIRTCPM) |
				 (input_masks->dst_port_mask << 16)));
				 (input_masks->dst_port_mask << 16)));
		break;
		break;
	case IXGBE_ATR_L4TYPE_UDP:
	case IXGBE_ATR_L4TYPE_UDP:
		if (src_port == 0)
		IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, input_masks->src_port_mask);
			IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, 0xffff);
		else
			IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM,
			                input_masks->src_port_mask);

		if (dst_port == 0)
			IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM,
			               (IXGBE_READ_REG(hw, IXGBE_FDIRUDPM) |
			                (0xffff << 16)));
		else
		IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM,
		IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM,
				(IXGBE_READ_REG(hw, IXGBE_FDIRUDPM) |
				(IXGBE_READ_REG(hw, IXGBE_FDIRUDPM) |
				 (input_masks->src_port_mask << 16)));
				 (input_masks->src_port_mask << 16)));
@@ -1967,11 +1938,11 @@ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
	}
	}


	/* Program the last mask register, FDIRM */
	/* Program the last mask register, FDIRM */
	if (input_masks->vlan_id_mask || !vlan_id)
	if (input_masks->vlan_id_mask)
		/* Mask both VLAN and VLANP - bits 0 and 1 */
		/* Mask both VLAN and VLANP - bits 0 and 1 */
		fdirm |= 0x3;
		fdirm |= 0x3;


	if (input_masks->data_mask || !flex_bytes)
	if (input_masks->data_mask)
		/* Flex bytes need masking, so mask the whole thing - bit 4 */
		/* Flex bytes need masking, so mask the whole thing - bit 4 */
		fdirm |= 0x10;
		fdirm |= 0x10;


+3 −2
Original line number Original line Diff line number Diff line
@@ -470,8 +470,9 @@ struct ethtool_rxfh_indir {
 * @action: RX ring/queue index to deliver to (non-negative) or other action
 * @action: RX ring/queue index to deliver to (non-negative) or other action
 *	(negative, e.g. %ETHTOOL_RXNTUPLE_ACTION_DROP)
 *	(negative, e.g. %ETHTOOL_RXNTUPLE_ACTION_DROP)
 *
 *
 * Zero values in @h_u may be ignored, as if all the corresponding
 * For flow types %TCP_V4_FLOW, %UDP_V4_FLOW and %SCTP_V4_FLOW, where
 * mask bits were set.
 * a field value and mask are both zero this is treated as if all mask
 * bits are set i.e. the field is ignored.
 */
 */
struct ethtool_rx_ntuple_flow_spec {
struct ethtool_rx_ntuple_flow_spec {
	__u32		 flow_type;
	__u32		 flow_type;
+34 −0
Original line number Original line Diff line number Diff line
@@ -485,6 +485,38 @@ static void __rx_ntuple_filter_add(struct ethtool_rx_ntuple_list *list,
	list->count++;
	list->count++;
}
}


/*
 * ethtool does not (or did not) set masks for flow parameters that are
 * not specified, so if both value and mask are 0 then this must be
 * treated as equivalent to a mask with all bits set.  Implement that
 * here rather than in drivers.
 */
static void rx_ntuple_fix_masks(struct ethtool_rx_ntuple_flow_spec *fs)
{
	struct ethtool_tcpip4_spec *entry = &fs->h_u.tcp_ip4_spec;
	struct ethtool_tcpip4_spec *mask = &fs->m_u.tcp_ip4_spec;

	if (fs->flow_type != TCP_V4_FLOW &&
	    fs->flow_type != UDP_V4_FLOW &&
	    fs->flow_type != SCTP_V4_FLOW)
		return;

	if (!(entry->ip4src | mask->ip4src))
		mask->ip4src = htonl(0xffffffff);
	if (!(entry->ip4dst | mask->ip4dst))
		mask->ip4dst = htonl(0xffffffff);
	if (!(entry->psrc | mask->psrc))
		mask->psrc = htons(0xffff);
	if (!(entry->pdst | mask->pdst))
		mask->pdst = htons(0xffff);
	if (!(entry->tos | mask->tos))
		mask->tos = 0xff;
	if (!(fs->vlan_tag | fs->vlan_tag_mask))
		fs->vlan_tag_mask = 0xffff;
	if (!(fs->data | fs->data_mask))
		fs->data_mask = 0xffffffffffffffffULL;
}

static noinline_for_stack int ethtool_set_rx_ntuple(struct net_device *dev,
static noinline_for_stack int ethtool_set_rx_ntuple(struct net_device *dev,
						    void __user *useraddr)
						    void __user *useraddr)
{
{
@@ -499,6 +531,8 @@ static noinline_for_stack int ethtool_set_rx_ntuple(struct net_device *dev,
	if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
	if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
		return -EFAULT;
		return -EFAULT;


	rx_ntuple_fix_masks(&cmd.fs);

	/*
	/*
	 * Cache filter in dev struct for GET operation only if
	 * Cache filter in dev struct for GET operation only if
	 * the underlying driver doesn't have its own GET operation, and
	 * the underlying driver doesn't have its own GET operation, and