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: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
					parent
					
						
							
								3b27e10555
							
						
					
				
			
			
				commit
				
					
						be2902daee
					
				
			
		
					 3 changed files with 51 additions and 45 deletions
				
			
		| 
						 | 
					@ -1910,56 +1910,27 @@ 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, input_masks->src_ip_mask);
 | 
				
			||||||
		IXGBE_WRITE_REG(hw, IXGBE_FDIRSIP4M, 0xffffffff);
 | 
						IXGBE_WRITE_REG(hw, IXGBE_FDIRDIP4M, input_masks->dst_ip_mask);
 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		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);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	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);
 | 
							IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM,
 | 
				
			||||||
		else
 | 
									(IXGBE_READ_REG(hw, IXGBE_FDIRTCPM) |
 | 
				
			||||||
			IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM,
 | 
									 (input_masks->dst_port_mask << 16)));
 | 
				
			||||||
			                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_READ_REG(hw, IXGBE_FDIRTCPM) |
 | 
					 | 
				
			||||||
			                (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);
 | 
							IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM,
 | 
				
			||||||
		else
 | 
									(IXGBE_READ_REG(hw, IXGBE_FDIRUDPM) |
 | 
				
			||||||
			IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM,
 | 
									 (input_masks->src_port_mask << 16)));
 | 
				
			||||||
			                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_READ_REG(hw, IXGBE_FDIRUDPM) |
 | 
					 | 
				
			||||||
			                (input_masks->src_port_mask << 16)));
 | 
					 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		/* this already would have failed above */
 | 
							/* this already would have failed above */
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue