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;
}