]> Git Repo - J-linux.git/blob - drivers/net/ethernet/google/gve/gve_flow_rule.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / drivers / net / ethernet / google / gve / gve_flow_rule.c
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 }
This page took 0.047173 seconds and 4 git commands to generate.