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