Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netdevsim: add dummy macsec offload

When the kernel is compiled with MACsec support, add the
NETIF_F_HW_MACSEC feature to netdevsim devices and implement
macsec_ops.

To allow easy testing of failure from the device, support is limited
to 3 SecY's per netdevsim device, and 1 RXSC per SecY.

v2:
- nsim_macsec_add_secy, return -ENOSPC if secy_count isn't full but
we can't find an empty slot (Simon Horman)
- add sci_to_cpu to make sparse happy (Simon Horman)
- remove set but not used secy variable (kernel test robot and
Simon Horman)

Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
Reviewed-by: Simon Horman <simon.horman@corigine.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Sabrina Dubroca and committed by
David S. Miller
02b34d03 633d76ad

+397
+4
drivers/net/netdevsim/Makefile
··· 17 17 ifneq ($(CONFIG_PSAMPLE),) 18 18 netdevsim-objs += psample.o 19 19 endif 20 + 21 + ifneq ($(CONFIG_MACSEC),) 22 + netdevsim-objs += macsec.o 23 + endif
+356
drivers/net/netdevsim/macsec.c
··· 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 + }
+3
drivers/net/netdevsim/netdev.c
··· 304 304 if (err) 305 305 goto err_utn_destroy; 306 306 307 + nsim_macsec_init(ns); 307 308 nsim_ipsec_init(ns); 308 309 309 310 err = register_netdevice(ns->netdev); ··· 315 314 316 315 err_ipsec_teardown: 317 316 nsim_ipsec_teardown(ns); 317 + nsim_macsec_teardown(ns); 318 318 nsim_bpf_uninit(ns); 319 319 err_utn_destroy: 320 320 rtnl_unlock(); ··· 376 374 rtnl_lock(); 377 375 unregister_netdevice(dev); 378 376 if (nsim_dev_port_is_pf(ns->nsim_dev_port)) { 377 + nsim_macsec_teardown(ns); 379 378 nsim_ipsec_teardown(ns); 380 379 nsim_bpf_uninit(ns); 381 380 }
+34
drivers/net/netdevsim/netdevsim.h
··· 23 23 #include <net/devlink.h> 24 24 #include <net/udp_tunnel.h> 25 25 #include <net/xdp.h> 26 + #include <net/macsec.h> 26 27 27 28 #define DRV_NAME "netdevsim" 28 29 ··· 51 50 u32 count; 52 51 u32 tx; 53 52 u32 ok; 53 + }; 54 + 55 + #define NSIM_MACSEC_MAX_SECY_COUNT 3 56 + #define NSIM_MACSEC_MAX_RXSC_COUNT 1 57 + struct nsim_rxsc { 58 + sci_t sci; 59 + bool used; 60 + }; 61 + 62 + struct nsim_secy { 63 + sci_t sci; 64 + struct nsim_rxsc nsim_rxsc[NSIM_MACSEC_MAX_RXSC_COUNT]; 65 + u8 nsim_rxsc_count; 66 + bool used; 67 + }; 68 + 69 + struct nsim_macsec { 70 + struct nsim_secy nsim_secy[NSIM_MACSEC_MAX_SECY_COUNT]; 71 + u8 nsim_secy_count; 54 72 }; 55 73 56 74 struct nsim_ethtool_pauseparam { ··· 113 93 114 94 bool bpf_map_accept; 115 95 struct nsim_ipsec ipsec; 96 + struct nsim_macsec macsec; 116 97 struct { 117 98 u32 inject_error; 118 99 u32 sleep; ··· 384 363 static inline bool nsim_ipsec_tx(struct netdevsim *ns, struct sk_buff *skb) 385 364 { 386 365 return true; 366 + } 367 + #endif 368 + 369 + #if IS_ENABLED(CONFIG_MACSEC) 370 + void nsim_macsec_init(struct netdevsim *ns); 371 + void nsim_macsec_teardown(struct netdevsim *ns); 372 + #else 373 + static inline void nsim_macsec_init(struct netdevsim *ns) 374 + { 375 + } 376 + 377 + static inline void nsim_macsec_teardown(struct netdevsim *ns) 378 + { 387 379 } 388 380 #endif 389 381