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 %016llx 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 %016llx 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 %016llx 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 %016llx 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 %016llx 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 %016llx 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 %016llx 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 %016llx 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 %016llx 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 %016llx 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 %016llx 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 %016llx 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 %016llx 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 %016llx 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 %016llx 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 %016llx, 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 %016llx 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 %016llx 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 %016llx, 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 %016llx 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 %016llx 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 %016llx, 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 %016llx 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 %016llx, 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 %016llx 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 %016llx, 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 %016llx 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 %016llx, 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