1 // SPDX-License-Identifier: (GPL-2.0 OR MIT) 2 /* Google virtual Ethernet (gve) driver 3 * 4 * Copyright (C) 2015-2024 Google LLC 5 */ 6 7 #include "gve.h" 8 #include "gve_adminq.h" 9 10 static 11 int gve_fill_ethtool_flow_spec(struct ethtool_rx_flow_spec *fsp, 12 struct gve_adminq_queried_flow_rule *rule) 13 { 14 struct gve_adminq_flow_rule *flow_rule = &rule->flow_rule; 15 static const u16 flow_type_lut[] = { 16 [GVE_FLOW_TYPE_TCPV4] = TCP_V4_FLOW, 17 [GVE_FLOW_TYPE_UDPV4] = UDP_V4_FLOW, 18 [GVE_FLOW_TYPE_SCTPV4] = SCTP_V4_FLOW, 19 [GVE_FLOW_TYPE_AHV4] = AH_V4_FLOW, 20 [GVE_FLOW_TYPE_ESPV4] = ESP_V4_FLOW, 21 [GVE_FLOW_TYPE_TCPV6] = TCP_V6_FLOW, 22 [GVE_FLOW_TYPE_UDPV6] = UDP_V6_FLOW, 23 [GVE_FLOW_TYPE_SCTPV6] = SCTP_V6_FLOW, 24 [GVE_FLOW_TYPE_AHV6] = AH_V6_FLOW, 25 [GVE_FLOW_TYPE_ESPV6] = ESP_V6_FLOW, 26 }; 27 28 if (be16_to_cpu(flow_rule->flow_type) >= ARRAY_SIZE(flow_type_lut)) 29 return -EINVAL; 30 31 fsp->flow_type = flow_type_lut[be16_to_cpu(flow_rule->flow_type)]; 32 33 memset(&fsp->h_u, 0, sizeof(fsp->h_u)); 34 memset(&fsp->h_ext, 0, sizeof(fsp->h_ext)); 35 memset(&fsp->m_u, 0, sizeof(fsp->m_u)); 36 memset(&fsp->m_ext, 0, sizeof(fsp->m_ext)); 37 38 switch (fsp->flow_type) { 39 case TCP_V4_FLOW: 40 case UDP_V4_FLOW: 41 case SCTP_V4_FLOW: 42 fsp->h_u.tcp_ip4_spec.ip4src = flow_rule->key.src_ip[0]; 43 fsp->h_u.tcp_ip4_spec.ip4dst = flow_rule->key.dst_ip[0]; 44 fsp->h_u.tcp_ip4_spec.psrc = flow_rule->key.src_port; 45 fsp->h_u.tcp_ip4_spec.pdst = flow_rule->key.dst_port; 46 fsp->h_u.tcp_ip4_spec.tos = flow_rule->key.tos; 47 fsp->m_u.tcp_ip4_spec.ip4src = flow_rule->mask.src_ip[0]; 48 fsp->m_u.tcp_ip4_spec.ip4dst = flow_rule->mask.dst_ip[0]; 49 fsp->m_u.tcp_ip4_spec.psrc = flow_rule->mask.src_port; 50 fsp->m_u.tcp_ip4_spec.pdst = flow_rule->mask.dst_port; 51 fsp->m_u.tcp_ip4_spec.tos = flow_rule->mask.tos; 52 break; 53 case AH_V4_FLOW: 54 case ESP_V4_FLOW: 55 fsp->h_u.ah_ip4_spec.ip4src = flow_rule->key.src_ip[0]; 56 fsp->h_u.ah_ip4_spec.ip4dst = flow_rule->key.dst_ip[0]; 57 fsp->h_u.ah_ip4_spec.spi = flow_rule->key.spi; 58 fsp->h_u.ah_ip4_spec.tos = flow_rule->key.tos; 59 fsp->m_u.ah_ip4_spec.ip4src = flow_rule->mask.src_ip[0]; 60 fsp->m_u.ah_ip4_spec.ip4dst = flow_rule->mask.dst_ip[0]; 61 fsp->m_u.ah_ip4_spec.spi = flow_rule->mask.spi; 62 fsp->m_u.ah_ip4_spec.tos = flow_rule->mask.tos; 63 break; 64 case TCP_V6_FLOW: 65 case UDP_V6_FLOW: 66 case SCTP_V6_FLOW: 67 memcpy(fsp->h_u.tcp_ip6_spec.ip6src, &flow_rule->key.src_ip, 68 sizeof(struct in6_addr)); 69 memcpy(fsp->h_u.tcp_ip6_spec.ip6dst, &flow_rule->key.dst_ip, 70 sizeof(struct in6_addr)); 71 fsp->h_u.tcp_ip6_spec.psrc = flow_rule->key.src_port; 72 fsp->h_u.tcp_ip6_spec.pdst = flow_rule->key.dst_port; 73 fsp->h_u.tcp_ip6_spec.tclass = flow_rule->key.tclass; 74 memcpy(fsp->m_u.tcp_ip6_spec.ip6src, &flow_rule->mask.src_ip, 75 sizeof(struct in6_addr)); 76 memcpy(fsp->m_u.tcp_ip6_spec.ip6dst, &flow_rule->mask.dst_ip, 77 sizeof(struct in6_addr)); 78 fsp->m_u.tcp_ip6_spec.psrc = flow_rule->mask.src_port; 79 fsp->m_u.tcp_ip6_spec.pdst = flow_rule->mask.dst_port; 80 fsp->m_u.tcp_ip6_spec.tclass = flow_rule->mask.tclass; 81 break; 82 case AH_V6_FLOW: 83 case ESP_V6_FLOW: 84 memcpy(fsp->h_u.ah_ip6_spec.ip6src, &flow_rule->key.src_ip, 85 sizeof(struct in6_addr)); 86 memcpy(fsp->h_u.ah_ip6_spec.ip6dst, &flow_rule->key.dst_ip, 87 sizeof(struct in6_addr)); 88 fsp->h_u.ah_ip6_spec.spi = flow_rule->key.spi; 89 fsp->h_u.ah_ip6_spec.tclass = flow_rule->key.tclass; 90 memcpy(fsp->m_u.ah_ip6_spec.ip6src, &flow_rule->mask.src_ip, 91 sizeof(struct in6_addr)); 92 memcpy(fsp->m_u.ah_ip6_spec.ip6dst, &flow_rule->mask.dst_ip, 93 sizeof(struct in6_addr)); 94 fsp->m_u.ah_ip6_spec.spi = flow_rule->mask.spi; 95 fsp->m_u.ah_ip6_spec.tclass = flow_rule->mask.tclass; 96 break; 97 default: 98 return -EINVAL; 99 } 100 101 fsp->ring_cookie = be16_to_cpu(flow_rule->action); 102 103 return 0; 104 } 105 106 static int gve_generate_flow_rule(struct gve_priv *priv, struct ethtool_rx_flow_spec *fsp, 107 struct gve_adminq_flow_rule *rule) 108 { 109 static const u16 flow_type_lut[] = { 110 [TCP_V4_FLOW] = GVE_FLOW_TYPE_TCPV4, 111 [UDP_V4_FLOW] = GVE_FLOW_TYPE_UDPV4, 112 [SCTP_V4_FLOW] = GVE_FLOW_TYPE_SCTPV4, 113 [AH_V4_FLOW] = GVE_FLOW_TYPE_AHV4, 114 [ESP_V4_FLOW] = GVE_FLOW_TYPE_ESPV4, 115 [TCP_V6_FLOW] = GVE_FLOW_TYPE_TCPV6, 116 [UDP_V6_FLOW] = GVE_FLOW_TYPE_UDPV6, 117 [SCTP_V6_FLOW] = GVE_FLOW_TYPE_SCTPV6, 118 [AH_V6_FLOW] = GVE_FLOW_TYPE_AHV6, 119 [ESP_V6_FLOW] = GVE_FLOW_TYPE_ESPV6, 120 }; 121 u32 flow_type; 122 123 if (fsp->ring_cookie == RX_CLS_FLOW_DISC) 124 return -EOPNOTSUPP; 125 126 if (fsp->ring_cookie >= priv->rx_cfg.num_queues) 127 return -EINVAL; 128 129 rule->action = cpu_to_be16(fsp->ring_cookie); 130 131 flow_type = fsp->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT | FLOW_RSS); 132 if (!flow_type || flow_type >= ARRAY_SIZE(flow_type_lut)) 133 return -EINVAL; 134 135 rule->flow_type = cpu_to_be16(flow_type_lut[flow_type]); 136 137 switch (flow_type) { 138 case TCP_V4_FLOW: 139 case UDP_V4_FLOW: 140 case SCTP_V4_FLOW: 141 rule->key.src_ip[0] = fsp->h_u.tcp_ip4_spec.ip4src; 142 rule->key.dst_ip[0] = fsp->h_u.tcp_ip4_spec.ip4dst; 143 rule->key.src_port = fsp->h_u.tcp_ip4_spec.psrc; 144 rule->key.dst_port = fsp->h_u.tcp_ip4_spec.pdst; 145 rule->mask.src_ip[0] = fsp->m_u.tcp_ip4_spec.ip4src; 146 rule->mask.dst_ip[0] = fsp->m_u.tcp_ip4_spec.ip4dst; 147 rule->mask.src_port = fsp->m_u.tcp_ip4_spec.psrc; 148 rule->mask.dst_port = fsp->m_u.tcp_ip4_spec.pdst; 149 break; 150 case AH_V4_FLOW: 151 case ESP_V4_FLOW: 152 rule->key.src_ip[0] = fsp->h_u.tcp_ip4_spec.ip4src; 153 rule->key.dst_ip[0] = fsp->h_u.tcp_ip4_spec.ip4dst; 154 rule->key.spi = fsp->h_u.ah_ip4_spec.spi; 155 rule->mask.src_ip[0] = fsp->m_u.tcp_ip4_spec.ip4src; 156 rule->mask.dst_ip[0] = fsp->m_u.tcp_ip4_spec.ip4dst; 157 rule->mask.spi = fsp->m_u.ah_ip4_spec.spi; 158 break; 159 case TCP_V6_FLOW: 160 case UDP_V6_FLOW: 161 case SCTP_V6_FLOW: 162 memcpy(&rule->key.src_ip, fsp->h_u.tcp_ip6_spec.ip6src, 163 sizeof(struct in6_addr)); 164 memcpy(&rule->key.dst_ip, fsp->h_u.tcp_ip6_spec.ip6dst, 165 sizeof(struct in6_addr)); 166 rule->key.src_port = fsp->h_u.tcp_ip6_spec.psrc; 167 rule->key.dst_port = fsp->h_u.tcp_ip6_spec.pdst; 168 memcpy(&rule->mask.src_ip, fsp->m_u.tcp_ip6_spec.ip6src, 169 sizeof(struct in6_addr)); 170 memcpy(&rule->mask.dst_ip, fsp->m_u.tcp_ip6_spec.ip6dst, 171 sizeof(struct in6_addr)); 172 rule->mask.src_port = fsp->m_u.tcp_ip6_spec.psrc; 173 rule->mask.dst_port = fsp->m_u.tcp_ip6_spec.pdst; 174 break; 175 case AH_V6_FLOW: 176 case ESP_V6_FLOW: 177 memcpy(&rule->key.src_ip, fsp->h_u.usr_ip6_spec.ip6src, 178 sizeof(struct in6_addr)); 179 memcpy(&rule->key.dst_ip, fsp->h_u.usr_ip6_spec.ip6dst, 180 sizeof(struct in6_addr)); 181 rule->key.spi = fsp->h_u.ah_ip6_spec.spi; 182 memcpy(&rule->mask.src_ip, fsp->m_u.usr_ip6_spec.ip6src, 183 sizeof(struct in6_addr)); 184 memcpy(&rule->mask.dst_ip, fsp->m_u.usr_ip6_spec.ip6dst, 185 sizeof(struct in6_addr)); 186 rule->key.spi = fsp->h_u.ah_ip6_spec.spi; 187 break; 188 default: 189 /* not doing un-parsed flow types */ 190 return -EINVAL; 191 } 192 193 return 0; 194 } 195 196 int gve_get_flow_rule_entry(struct gve_priv *priv, struct ethtool_rxnfc *cmd) 197 { 198 struct gve_adminq_queried_flow_rule *rules_cache = priv->flow_rules_cache.rules_cache; 199 struct ethtool_rx_flow_spec *fsp = (struct ethtool_rx_flow_spec *)&cmd->fs; 200 u32 *cache_num = &priv->flow_rules_cache.rules_cache_num; 201 struct gve_adminq_queried_flow_rule *rule = NULL; 202 int err = 0; 203 u32 i; 204 205 if (!priv->max_flow_rules) 206 return -EOPNOTSUPP; 207 208 if (!priv->flow_rules_cache.rules_cache_synced || 209 fsp->location < be32_to_cpu(rules_cache[0].location) || 210 fsp->location > be32_to_cpu(rules_cache[*cache_num - 1].location)) { 211 err = gve_adminq_query_flow_rules(priv, GVE_FLOW_RULE_QUERY_RULES, fsp->location); 212 if (err) 213 return err; 214 215 priv->flow_rules_cache.rules_cache_synced = true; 216 } 217 218 for (i = 0; i < *cache_num; i++) { 219 if (fsp->location == be32_to_cpu(rules_cache[i].location)) { 220 rule = &rules_cache[i]; 221 break; 222 } 223 } 224 225 if (!rule) 226 return -EINVAL; 227 228 err = gve_fill_ethtool_flow_spec(fsp, rule); 229 230 return err; 231 } 232 233 int gve_get_flow_rule_ids(struct gve_priv *priv, struct ethtool_rxnfc *cmd, u32 *rule_locs) 234 { 235 __be32 *rule_ids_cache = priv->flow_rules_cache.rule_ids_cache; 236 u32 *cache_num = &priv->flow_rules_cache.rule_ids_cache_num; 237 u32 starting_rule_id = 0; 238 u32 i = 0, j = 0; 239 int err = 0; 240 241 if (!priv->max_flow_rules) 242 return -EOPNOTSUPP; 243 244 do { 245 err = gve_adminq_query_flow_rules(priv, GVE_FLOW_RULE_QUERY_IDS, 246 starting_rule_id); 247 if (err) 248 return err; 249 250 for (i = 0; i < *cache_num; i++) { 251 if (j >= cmd->rule_cnt) 252 return -EMSGSIZE; 253 254 rule_locs[j++] = be32_to_cpu(rule_ids_cache[i]); 255 starting_rule_id = be32_to_cpu(rule_ids_cache[i]) + 1; 256 } 257 } while (*cache_num != 0); 258 cmd->data = priv->max_flow_rules; 259 260 return err; 261 } 262 263 int gve_add_flow_rule(struct gve_priv *priv, struct ethtool_rxnfc *cmd) 264 { 265 struct ethtool_rx_flow_spec *fsp = &cmd->fs; 266 struct gve_adminq_flow_rule *rule = NULL; 267 int err; 268 269 if (!priv->max_flow_rules) 270 return -EOPNOTSUPP; 271 272 rule = kvzalloc(sizeof(*rule), GFP_KERNEL); 273 if (!rule) 274 return -ENOMEM; 275 276 err = gve_generate_flow_rule(priv, fsp, rule); 277 if (err) 278 goto out; 279 280 err = gve_adminq_add_flow_rule(priv, rule, fsp->location); 281 282 out: 283 kvfree(rule); 284 if (err) 285 dev_err(&priv->pdev->dev, "Failed to add the flow rule: %u", fsp->location); 286 287 return err; 288 } 289 290 int gve_del_flow_rule(struct gve_priv *priv, struct ethtool_rxnfc *cmd) 291 { 292 struct ethtool_rx_flow_spec *fsp = (struct ethtool_rx_flow_spec *)&cmd->fs; 293 294 if (!priv->max_flow_rules) 295 return -EOPNOTSUPP; 296 297 return gve_adminq_del_flow_rule(priv, fsp->location); 298 } 299