1 // SPDX-License-Identifier: GPL-2.0
2
3 #include <net/macsec.h>
4 #include "netdevsim.h"
5
nsim_macsec_find_secy(struct netdevsim * ns,sci_t sci)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
nsim_macsec_find_rxsc(struct nsim_secy * ns_secy,sci_t sci)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
nsim_macsec_add_secy(struct macsec_context * ctx)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
nsim_macsec_upd_secy(struct macsec_context * ctx)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
nsim_macsec_del_secy(struct macsec_context * ctx)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
nsim_macsec_add_rxsc(struct macsec_context * ctx)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
nsim_macsec_upd_rxsc(struct macsec_context * ctx)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
nsim_macsec_del_rxsc(struct macsec_context * ctx)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
nsim_macsec_add_rxsa(struct macsec_context * ctx)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
nsim_macsec_upd_rxsa(struct macsec_context * ctx)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
nsim_macsec_del_rxsa(struct macsec_context * ctx)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
nsim_macsec_add_txsa(struct macsec_context * ctx)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
nsim_macsec_upd_txsa(struct macsec_context * ctx)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
nsim_macsec_del_txsa(struct macsec_context * ctx)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
nsim_macsec_init(struct netdevsim * ns)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
nsim_macsec_teardown(struct netdevsim * ns)349 void nsim_macsec_teardown(struct netdevsim *ns)
350 {
351 }
352