gve_flow_rule.c 9.2 KB

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