xref: /linux/drivers/net/netdevsim/macsec.c (revision 03c11eb3b16dc0058589751dfd91f254be2be613)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 #include <net/macsec.h>
4 #include "netdevsim.h"
5 
6 static int nsim_macsec_find_secy(struct netdevsim *ns, sci_t sci)
7 {
8 	int i;
9 
10 	for (i = 0; i < NSIM_MACSEC_MAX_SECY_COUNT; i++) {
11 		if (ns->macsec.nsim_secy[i].sci == sci)
12 			return i;
13 	}
14 
15 	return -1;
16 }
17 
18 static int nsim_macsec_find_rxsc(struct nsim_secy *ns_secy, sci_t sci)
19 {
20 	int i;
21 
22 	for (i = 0; i < NSIM_MACSEC_MAX_RXSC_COUNT; i++) {
23 		if (ns_secy->nsim_rxsc[i].sci == sci)
24 			return i;
25 	}
26 
27 	return -1;
28 }
29 
30 static int nsim_macsec_add_secy(struct macsec_context *ctx)
31 {
32 	struct netdevsim *ns = netdev_priv(ctx->netdev);
33 	int idx;
34 
35 	if (ns->macsec.nsim_secy_count == NSIM_MACSEC_MAX_SECY_COUNT)
36 		return -ENOSPC;
37 
38 	for (idx = 0; idx < NSIM_MACSEC_MAX_SECY_COUNT; idx++) {
39 		if (!ns->macsec.nsim_secy[idx].used)
40 			break;
41 	}
42 
43 	if (idx == NSIM_MACSEC_MAX_SECY_COUNT) {
44 		netdev_err(ctx->netdev, "%s: nsim_secy_count not full but all SecYs used\n",
45 			   __func__);
46 		return -ENOSPC;
47 	}
48 
49 	netdev_dbg(ctx->netdev, "%s: adding new secy with sci %08llx at index %d\n",
50 		   __func__, sci_to_cpu(ctx->secy->sci), idx);
51 	ns->macsec.nsim_secy[idx].used = true;
52 	ns->macsec.nsim_secy[idx].nsim_rxsc_count = 0;
53 	ns->macsec.nsim_secy[idx].sci = ctx->secy->sci;
54 	ns->macsec.nsim_secy_count++;
55 
56 	return 0;
57 }
58 
59 static int nsim_macsec_upd_secy(struct macsec_context *ctx)
60 {
61 	struct netdevsim *ns = netdev_priv(ctx->netdev);
62 	int idx;
63 
64 	idx = nsim_macsec_find_secy(ns, ctx->secy->sci);
65 	if (idx < 0) {
66 		netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n",
67 			   __func__, sci_to_cpu(ctx->secy->sci));
68 		return -ENOENT;
69 	}
70 
71 	netdev_dbg(ctx->netdev, "%s: updating secy with sci %08llx at index %d\n",
72 		   __func__, sci_to_cpu(ctx->secy->sci), idx);
73 
74 	return 0;
75 }
76 
77 static int nsim_macsec_del_secy(struct macsec_context *ctx)
78 {
79 	struct netdevsim *ns = netdev_priv(ctx->netdev);
80 	int idx;
81 
82 	idx = nsim_macsec_find_secy(ns, ctx->secy->sci);
83 	if (idx < 0) {
84 		netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n",
85 			   __func__, sci_to_cpu(ctx->secy->sci));
86 		return -ENOENT;
87 	}
88 
89 	netdev_dbg(ctx->netdev, "%s: removing SecY with SCI %08llx at index %d\n",
90 		   __func__, sci_to_cpu(ctx->secy->sci), idx);
91 
92 	ns->macsec.nsim_secy[idx].used = false;
93 	memset(&ns->macsec.nsim_secy[idx], 0, sizeof(ns->macsec.nsim_secy[idx]));
94 	ns->macsec.nsim_secy_count--;
95 
96 	return 0;
97 }
98 
99 static int nsim_macsec_add_rxsc(struct macsec_context *ctx)
100 {
101 	struct netdevsim *ns = netdev_priv(ctx->netdev);
102 	struct nsim_secy *secy;
103 	int idx;
104 
105 	idx = nsim_macsec_find_secy(ns, ctx->secy->sci);
106 	if (idx < 0) {
107 		netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n",
108 			   __func__, sci_to_cpu(ctx->secy->sci));
109 		return -ENOENT;
110 	}
111 	secy = &ns->macsec.nsim_secy[idx];
112 
113 	if (secy->nsim_rxsc_count == NSIM_MACSEC_MAX_RXSC_COUNT)
114 		return -ENOSPC;
115 
116 	for (idx = 0; idx < NSIM_MACSEC_MAX_RXSC_COUNT; idx++) {
117 		if (!secy->nsim_rxsc[idx].used)
118 			break;
119 	}
120 
121 	if (idx == NSIM_MACSEC_MAX_RXSC_COUNT)
122 		netdev_err(ctx->netdev, "%s: nsim_rxsc_count not full but all RXSCs used\n",
123 			   __func__);
124 
125 	netdev_dbg(ctx->netdev, "%s: adding new rxsc with sci %08llx at index %d\n",
126 		   __func__, sci_to_cpu(ctx->rx_sc->sci), idx);
127 	secy->nsim_rxsc[idx].used = true;
128 	secy->nsim_rxsc[idx].sci = ctx->rx_sc->sci;
129 	secy->nsim_rxsc_count++;
130 
131 	return 0;
132 }
133 
134 static int nsim_macsec_upd_rxsc(struct macsec_context *ctx)
135 {
136 	struct netdevsim *ns = netdev_priv(ctx->netdev);
137 	struct nsim_secy *secy;
138 	int idx;
139 
140 	idx = nsim_macsec_find_secy(ns, ctx->secy->sci);
141 	if (idx < 0) {
142 		netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n",
143 			   __func__, sci_to_cpu(ctx->secy->sci));
144 		return -ENOENT;
145 	}
146 	secy = &ns->macsec.nsim_secy[idx];
147 
148 	idx = nsim_macsec_find_rxsc(secy, ctx->rx_sc->sci);
149 	if (idx < 0) {
150 		netdev_err(ctx->netdev, "%s: sci %08llx not found in RXSC table\n",
151 			   __func__, sci_to_cpu(ctx->rx_sc->sci));
152 		return -ENOENT;
153 	}
154 
155 	netdev_dbg(ctx->netdev, "%s: updating RXSC with sci %08llx at index %d\n",
156 		   __func__, sci_to_cpu(ctx->rx_sc->sci), idx);
157 
158 	return 0;
159 }
160 
161 static int nsim_macsec_del_rxsc(struct macsec_context *ctx)
162 {
163 	struct netdevsim *ns = netdev_priv(ctx->netdev);
164 	struct nsim_secy *secy;
165 	int idx;
166 
167 	idx = nsim_macsec_find_secy(ns, ctx->secy->sci);
168 	if (idx < 0) {
169 		netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n",
170 			   __func__, sci_to_cpu(ctx->secy->sci));
171 		return -ENOENT;
172 	}
173 	secy = &ns->macsec.nsim_secy[idx];
174 
175 	idx = nsim_macsec_find_rxsc(secy, ctx->rx_sc->sci);
176 	if (idx < 0) {
177 		netdev_err(ctx->netdev, "%s: sci %08llx not found in RXSC table\n",
178 			   __func__, sci_to_cpu(ctx->rx_sc->sci));
179 		return -ENOENT;
180 	}
181 
182 	netdev_dbg(ctx->netdev, "%s: removing RXSC with sci %08llx at index %d\n",
183 		   __func__, sci_to_cpu(ctx->rx_sc->sci), idx);
184 
185 	secy->nsim_rxsc[idx].used = false;
186 	memset(&secy->nsim_rxsc[idx], 0, sizeof(secy->nsim_rxsc[idx]));
187 	secy->nsim_rxsc_count--;
188 
189 	return 0;
190 }
191 
192 static int nsim_macsec_add_rxsa(struct macsec_context *ctx)
193 {
194 	struct netdevsim *ns = netdev_priv(ctx->netdev);
195 	struct nsim_secy *secy;
196 	int idx;
197 
198 	idx = nsim_macsec_find_secy(ns, ctx->secy->sci);
199 	if (idx < 0) {
200 		netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n",
201 			   __func__, sci_to_cpu(ctx->secy->sci));
202 		return -ENOENT;
203 	}
204 	secy = &ns->macsec.nsim_secy[idx];
205 
206 	idx = nsim_macsec_find_rxsc(secy, ctx->sa.rx_sa->sc->sci);
207 	if (idx < 0) {
208 		netdev_err(ctx->netdev, "%s: sci %08llx not found in RXSC table\n",
209 			   __func__, sci_to_cpu(ctx->sa.rx_sa->sc->sci));
210 		return -ENOENT;
211 	}
212 
213 	netdev_dbg(ctx->netdev, "%s: RXSC with sci %08llx, AN %u\n",
214 		   __func__, sci_to_cpu(ctx->sa.rx_sa->sc->sci), ctx->sa.assoc_num);
215 
216 	return 0;
217 }
218 
219 static int nsim_macsec_upd_rxsa(struct macsec_context *ctx)
220 {
221 	struct netdevsim *ns = netdev_priv(ctx->netdev);
222 	struct nsim_secy *secy;
223 	int idx;
224 
225 	idx = nsim_macsec_find_secy(ns, ctx->secy->sci);
226 	if (idx < 0) {
227 		netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n",
228 			   __func__, sci_to_cpu(ctx->secy->sci));
229 		return -ENOENT;
230 	}
231 	secy = &ns->macsec.nsim_secy[idx];
232 
233 	idx = nsim_macsec_find_rxsc(secy, ctx->sa.rx_sa->sc->sci);
234 	if (idx < 0) {
235 		netdev_err(ctx->netdev, "%s: sci %08llx not found in RXSC table\n",
236 			   __func__, sci_to_cpu(ctx->sa.rx_sa->sc->sci));
237 		return -ENOENT;
238 	}
239 
240 	netdev_dbg(ctx->netdev, "%s: RXSC with sci %08llx, AN %u\n",
241 		   __func__, sci_to_cpu(ctx->sa.rx_sa->sc->sci), ctx->sa.assoc_num);
242 
243 	return 0;
244 }
245 
246 static int nsim_macsec_del_rxsa(struct macsec_context *ctx)
247 {
248 	struct netdevsim *ns = netdev_priv(ctx->netdev);
249 	struct nsim_secy *secy;
250 	int idx;
251 
252 	idx = nsim_macsec_find_secy(ns, ctx->secy->sci);
253 	if (idx < 0) {
254 		netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n",
255 			   __func__, sci_to_cpu(ctx->secy->sci));
256 		return -ENOENT;
257 	}
258 	secy = &ns->macsec.nsim_secy[idx];
259 
260 	idx = nsim_macsec_find_rxsc(secy, ctx->sa.rx_sa->sc->sci);
261 	if (idx < 0) {
262 		netdev_err(ctx->netdev, "%s: sci %08llx not found in RXSC table\n",
263 			   __func__, sci_to_cpu(ctx->sa.rx_sa->sc->sci));
264 		return -ENOENT;
265 	}
266 
267 	netdev_dbg(ctx->netdev, "%s: RXSC with sci %08llx, AN %u\n",
268 		   __func__, sci_to_cpu(ctx->sa.rx_sa->sc->sci), ctx->sa.assoc_num);
269 
270 	return 0;
271 }
272 
273 static int nsim_macsec_add_txsa(struct macsec_context *ctx)
274 {
275 	struct netdevsim *ns = netdev_priv(ctx->netdev);
276 	int idx;
277 
278 	idx = nsim_macsec_find_secy(ns, ctx->secy->sci);
279 	if (idx < 0) {
280 		netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n",
281 			   __func__, sci_to_cpu(ctx->secy->sci));
282 		return -ENOENT;
283 	}
284 
285 	netdev_dbg(ctx->netdev, "%s: SECY with sci %08llx, AN %u\n",
286 		   __func__, sci_to_cpu(ctx->secy->sci), ctx->sa.assoc_num);
287 
288 	return 0;
289 }
290 
291 static int nsim_macsec_upd_txsa(struct macsec_context *ctx)
292 {
293 	struct netdevsim *ns = netdev_priv(ctx->netdev);
294 	int idx;
295 
296 	idx = nsim_macsec_find_secy(ns, ctx->secy->sci);
297 	if (idx < 0) {
298 		netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n",
299 			   __func__, sci_to_cpu(ctx->secy->sci));
300 		return -ENOENT;
301 	}
302 
303 	netdev_dbg(ctx->netdev, "%s: SECY with sci %08llx, AN %u\n",
304 		   __func__, sci_to_cpu(ctx->secy->sci), ctx->sa.assoc_num);
305 
306 	return 0;
307 }
308 
309 static int nsim_macsec_del_txsa(struct macsec_context *ctx)
310 {
311 	struct netdevsim *ns = netdev_priv(ctx->netdev);
312 	int idx;
313 
314 	idx = nsim_macsec_find_secy(ns, ctx->secy->sci);
315 	if (idx < 0) {
316 		netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n",
317 			   __func__, sci_to_cpu(ctx->secy->sci));
318 		return -ENOENT;
319 	}
320 
321 	netdev_dbg(ctx->netdev, "%s: SECY with sci %08llx, AN %u\n",
322 		   __func__, sci_to_cpu(ctx->secy->sci), ctx->sa.assoc_num);
323 
324 	return 0;
325 }
326 
327 static const struct macsec_ops nsim_macsec_ops = {
328 	.mdo_add_secy = nsim_macsec_add_secy,
329 	.mdo_upd_secy = nsim_macsec_upd_secy,
330 	.mdo_del_secy = nsim_macsec_del_secy,
331 	.mdo_add_rxsc = nsim_macsec_add_rxsc,
332 	.mdo_upd_rxsc = nsim_macsec_upd_rxsc,
333 	.mdo_del_rxsc = nsim_macsec_del_rxsc,
334 	.mdo_add_rxsa = nsim_macsec_add_rxsa,
335 	.mdo_upd_rxsa = nsim_macsec_upd_rxsa,
336 	.mdo_del_rxsa = nsim_macsec_del_rxsa,
337 	.mdo_add_txsa = nsim_macsec_add_txsa,
338 	.mdo_upd_txsa = nsim_macsec_upd_txsa,
339 	.mdo_del_txsa = nsim_macsec_del_txsa,
340 };
341 
342 void nsim_macsec_init(struct netdevsim *ns)
343 {
344 	ns->netdev->macsec_ops = &nsim_macsec_ops;
345 	ns->netdev->features |= NETIF_F_HW_MACSEC;
346 	memset(&ns->macsec, 0, sizeof(ns->macsec));
347 }
348 
349 void nsim_macsec_teardown(struct netdevsim *ns)
350 {
351 }
352