xref: /linux/drivers/net/ethernet/google/gve/gve_flow_rule.c (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
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