352 lines · c
1// SPDX-License-Identifier: GPL-2.02 3#include <net/macsec.h>4#include "netdevsim.h"5 6static 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 18static 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 30static 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 59static 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 77static 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 99static 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 134static 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 161static 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 192static 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 219static 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 246static 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 273static 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 291static 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 309static 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 327static 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 342void 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 349void nsim_macsec_teardown(struct netdevsim *ns)350{351}352