static int gve_generate_flow_rule()

in google/gve/gve_flow_rule.c [106:194]


static int gve_generate_flow_rule(struct gve_priv *priv, struct ethtool_rx_flow_spec *fsp,
				  struct gve_adminq_flow_rule *rule)
{
	static const u16 flow_type_lut[] = {
		[TCP_V4_FLOW]	= GVE_FLOW_TYPE_TCPV4,
		[UDP_V4_FLOW]	= GVE_FLOW_TYPE_UDPV4,
		[SCTP_V4_FLOW]	= GVE_FLOW_TYPE_SCTPV4,
		[AH_V4_FLOW]	= GVE_FLOW_TYPE_AHV4,
		[ESP_V4_FLOW]	= GVE_FLOW_TYPE_ESPV4,
		[TCP_V6_FLOW]	= GVE_FLOW_TYPE_TCPV6,
		[UDP_V6_FLOW]	= GVE_FLOW_TYPE_UDPV6,
		[SCTP_V6_FLOW]	= GVE_FLOW_TYPE_SCTPV6,
		[AH_V6_FLOW]	= GVE_FLOW_TYPE_AHV6,
		[ESP_V6_FLOW]	= GVE_FLOW_TYPE_ESPV6,
	};
	u32 flow_type;

	if (fsp->ring_cookie == RX_CLS_FLOW_DISC)
		return -EOPNOTSUPP;

	if (fsp->ring_cookie >= priv->rx_cfg.num_queues)
		return -EINVAL;

	rule->action = cpu_to_be16(fsp->ring_cookie);

	flow_type = fsp->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT | FLOW_RSS);
	if (!flow_type || flow_type >= ARRAY_SIZE(flow_type_lut))
		return -EINVAL;

	rule->flow_type = cpu_to_be16(flow_type_lut[flow_type]);

	switch (flow_type) {
	case TCP_V4_FLOW:
	case UDP_V4_FLOW:
	case SCTP_V4_FLOW:
		rule->key.src_ip[0] = fsp->h_u.tcp_ip4_spec.ip4src;
		rule->key.dst_ip[0] = fsp->h_u.tcp_ip4_spec.ip4dst;
		rule->key.src_port = fsp->h_u.tcp_ip4_spec.psrc;
		rule->key.dst_port = fsp->h_u.tcp_ip4_spec.pdst;
		rule->mask.src_ip[0] = fsp->m_u.tcp_ip4_spec.ip4src;
		rule->mask.dst_ip[0] = fsp->m_u.tcp_ip4_spec.ip4dst;
		rule->mask.src_port = fsp->m_u.tcp_ip4_spec.psrc;
		rule->mask.dst_port = fsp->m_u.tcp_ip4_spec.pdst;
		break;
	case AH_V4_FLOW:
	case ESP_V4_FLOW:
		rule->key.src_ip[0] = fsp->h_u.tcp_ip4_spec.ip4src;
		rule->key.dst_ip[0] = fsp->h_u.tcp_ip4_spec.ip4dst;
		rule->key.spi = fsp->h_u.ah_ip4_spec.spi;
		rule->mask.src_ip[0] = fsp->m_u.tcp_ip4_spec.ip4src;
		rule->mask.dst_ip[0] = fsp->m_u.tcp_ip4_spec.ip4dst;
		rule->mask.spi = fsp->m_u.ah_ip4_spec.spi;
		break;
	case TCP_V6_FLOW:
	case UDP_V6_FLOW:
	case SCTP_V6_FLOW:
		memcpy(&rule->key.src_ip, fsp->h_u.tcp_ip6_spec.ip6src,
		       sizeof(struct in6_addr));
		memcpy(&rule->key.dst_ip, fsp->h_u.tcp_ip6_spec.ip6dst,
		       sizeof(struct in6_addr));
		rule->key.src_port = fsp->h_u.tcp_ip6_spec.psrc;
		rule->key.dst_port = fsp->h_u.tcp_ip6_spec.pdst;
		memcpy(&rule->mask.src_ip, fsp->m_u.tcp_ip6_spec.ip6src,
		       sizeof(struct in6_addr));
		memcpy(&rule->mask.dst_ip, fsp->m_u.tcp_ip6_spec.ip6dst,
		       sizeof(struct in6_addr));
		rule->mask.src_port = fsp->m_u.tcp_ip6_spec.psrc;
		rule->mask.dst_port = fsp->m_u.tcp_ip6_spec.pdst;
		break;
	case AH_V6_FLOW:
	case ESP_V6_FLOW:
		memcpy(&rule->key.src_ip, fsp->h_u.usr_ip6_spec.ip6src,
		       sizeof(struct in6_addr));
		memcpy(&rule->key.dst_ip, fsp->h_u.usr_ip6_spec.ip6dst,
		       sizeof(struct in6_addr));
		rule->key.spi = fsp->h_u.ah_ip6_spec.spi;
		memcpy(&rule->mask.src_ip, fsp->m_u.usr_ip6_spec.ip6src,
		       sizeof(struct in6_addr));
		memcpy(&rule->mask.dst_ip, fsp->m_u.usr_ip6_spec.ip6dst,
		       sizeof(struct in6_addr));
		rule->key.spi = fsp->h_u.ah_ip6_spec.spi;
		break;
	default:
		/* not doing un-parsed flow types */
		return -EINVAL;
	}

	return 0;
}