1 /* 2 * Wired Ethernet driver interface for QCA MACsec driver 3 * Copyright (c) 2005-2009, Jouni Malinen <j (at) w1.fi> 4 * Copyright (c) 2004, Gunter Burchardt <tira (at) isx.de> 5 * Copyright (c) 2013-2014, Qualcomm Atheros, Inc. 6 * 7 * This software may be distributed under the terms of the BSD license. 8 * See README for more details. 9 */ 10 11 #include "includes.h" 12 #include <sys/ioctl.h> 13 #include <net/if.h> 14 #include <inttypes.h> 15 #ifdef __linux__ 16 #include <netpacket/packet.h> 17 #include <net/if_arp.h> 18 #include <net/if.h> 19 #endif /* __linux__ */ 20 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) 21 #include <net/if_dl.h> 22 #include <net/if_media.h> 23 #endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) */ 24 #ifdef __sun__ 25 #include <sys/sockio.h> 26 #endif /* __sun__ */ 27 28 #include "utils/common.h" 29 #include "utils/eloop.h" 30 #include "common/defs.h" 31 #include "common/ieee802_1x_defs.h" 32 #include "pae/ieee802_1x_kay.h" 33 #include "driver.h" 34 #include "driver_wired_common.h" 35 36 #include "nss_macsec_secy.h" 37 #include "nss_macsec_secy_rx.h" 38 #include "nss_macsec_secy_tx.h" 39 40 #define MAXSC 16 41 42 /* TCI field definition */ 43 #define TCI_ES 0x40 44 #define TCI_SC 0x20 45 #define TCI_SCB 0x10 46 #define TCI_E 0x08 47 #define TCI_C 0x04 48 49 #ifdef _MSC_VER 50 #pragma pack(push, 1) 51 #endif /* _MSC_VER */ 52 53 #ifdef _MSC_VER 54 #pragma pack(pop) 55 #endif /* _MSC_VER */ 56 57 struct channel_map { 58 struct ieee802_1x_mka_sci sci; 59 }; 60 61 struct macsec_qca_data { 62 struct driver_wired_common_data common; 63 64 u32 secy_id; 65 66 /* shadow */ 67 Boolean always_include_sci; 68 Boolean use_es; 69 Boolean use_scb; 70 Boolean protect_frames; 71 Boolean replay_protect; 72 u32 replay_window; 73 74 struct channel_map receive_channel_map[MAXSC]; 75 struct channel_map transmit_channel_map[MAXSC]; 76 }; 77 78 79 static void __macsec_drv_init(struct macsec_qca_data *drv) 80 { 81 int ret = 0; 82 fal_rx_ctl_filt_t rx_ctl_filt; 83 fal_tx_ctl_filt_t tx_ctl_filt; 84 85 wpa_printf(MSG_INFO, "%s: secy_id=%d", __func__, drv->secy_id); 86 87 /* Enable Secy and Let EAPoL bypass */ 88 ret = nss_macsec_secy_en_set(drv->secy_id, TRUE); 89 if (ret) 90 wpa_printf(MSG_ERROR, "nss_macsec_secy_en_set: FAIL"); 91 92 ret = nss_macsec_secy_sc_sa_mapping_mode_set(drv->secy_id, 93 FAL_SC_SA_MAP_1_4); 94 if (ret) 95 wpa_printf(MSG_ERROR, 96 "nss_macsec_secy_sc_sa_mapping_mode_set: FAIL"); 97 98 os_memset(&rx_ctl_filt, 0, sizeof(rx_ctl_filt)); 99 rx_ctl_filt.bypass = 1; 100 rx_ctl_filt.match_type = IG_CTL_COMPARE_ETHER_TYPE; 101 rx_ctl_filt.match_mask = 0xffff; 102 rx_ctl_filt.ether_type_da_range = 0x888e; 103 ret = nss_macsec_secy_rx_ctl_filt_set(drv->secy_id, 0, &rx_ctl_filt); 104 if (ret) 105 wpa_printf(MSG_ERROR, "nss_macsec_secy_rx_ctl_filt_set: FAIL"); 106 107 os_memset(&tx_ctl_filt, 0, sizeof(tx_ctl_filt)); 108 tx_ctl_filt.bypass = 1; 109 tx_ctl_filt.match_type = EG_CTL_COMPARE_ETHER_TYPE; 110 tx_ctl_filt.match_mask = 0xffff; 111 tx_ctl_filt.ether_type_da_range = 0x888e; 112 ret = nss_macsec_secy_tx_ctl_filt_set(drv->secy_id, 0, &tx_ctl_filt); 113 if (ret) 114 wpa_printf(MSG_ERROR, "nss_macsec_secy_tx_ctl_filt_set: FAIL"); 115 } 116 117 118 static void __macsec_drv_deinit(struct macsec_qca_data *drv) 119 { 120 nss_macsec_secy_en_set(drv->secy_id, FALSE); 121 nss_macsec_secy_rx_sc_del_all(drv->secy_id); 122 nss_macsec_secy_tx_sc_del_all(drv->secy_id); 123 } 124 125 126 static void * macsec_qca_init(void *ctx, const char *ifname) 127 { 128 struct macsec_qca_data *drv; 129 130 drv = os_zalloc(sizeof(*drv)); 131 if (drv == NULL) 132 return NULL; 133 134 /* Board specific settings */ 135 if (os_memcmp("eth2", ifname, 4) == 0) 136 drv->secy_id = 1; 137 else if (os_memcmp("eth3", ifname, 4) == 0) 138 drv->secy_id = 2; 139 else 140 drv->secy_id = -1; 141 142 if (driver_wired_init_common(&drv->common, ifname, ctx) < 0) { 143 os_free(drv); 144 return NULL; 145 } 146 147 return drv; 148 } 149 150 151 static void macsec_qca_deinit(void *priv) 152 { 153 struct macsec_qca_data *drv = priv; 154 155 driver_wired_deinit_common(&drv->common); 156 os_free(drv); 157 } 158 159 160 static int macsec_qca_macsec_init(void *priv, struct macsec_init_params *params) 161 { 162 struct macsec_qca_data *drv = priv; 163 164 drv->always_include_sci = params->always_include_sci; 165 drv->use_es = params->use_es; 166 drv->use_scb = params->use_scb; 167 168 wpa_printf(MSG_DEBUG, "%s: es=%d, scb=%d, sci=%d", 169 __func__, drv->use_es, drv->use_scb, 170 drv->always_include_sci); 171 172 __macsec_drv_init(drv); 173 174 return 0; 175 } 176 177 178 static int macsec_qca_macsec_deinit(void *priv) 179 { 180 struct macsec_qca_data *drv = priv; 181 182 wpa_printf(MSG_DEBUG, "%s", __func__); 183 184 __macsec_drv_deinit(drv); 185 186 return 0; 187 } 188 189 190 static int macsec_qca_get_capability(void *priv, enum macsec_cap *cap) 191 { 192 wpa_printf(MSG_DEBUG, "%s", __func__); 193 194 *cap = MACSEC_CAP_INTEG_AND_CONF_0_30_50; 195 196 return 0; 197 } 198 199 200 static int macsec_qca_enable_protect_frames(void *priv, Boolean enabled) 201 { 202 struct macsec_qca_data *drv = priv; 203 int ret = 0; 204 205 wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); 206 207 drv->protect_frames = enabled; 208 209 return ret; 210 } 211 212 213 static int macsec_qca_set_replay_protect(void *priv, Boolean enabled, 214 unsigned int window) 215 { 216 struct macsec_qca_data *drv = priv; 217 int ret = 0; 218 219 wpa_printf(MSG_DEBUG, "%s: enabled=%d, win=%u", 220 __func__, enabled, window); 221 222 drv->replay_protect = enabled; 223 drv->replay_window = window; 224 225 return ret; 226 } 227 228 229 static int macsec_qca_set_current_cipher_suite(void *priv, u64 cs) 230 { 231 if (cs != CS_ID_GCM_AES_128) { 232 wpa_printf(MSG_ERROR, 233 "%s: NOT supported CipherSuite: %016" PRIx64, 234 __func__, cs); 235 return -1; 236 } 237 238 /* Support default Cipher Suite 0080020001000001 (GCM-AES-128) */ 239 wpa_printf(MSG_DEBUG, "%s: default support aes-gcm-128", __func__); 240 241 return 0; 242 } 243 244 245 static int macsec_qca_enable_controlled_port(void *priv, Boolean enabled) 246 { 247 struct macsec_qca_data *drv = priv; 248 int ret = 0; 249 250 wpa_printf(MSG_DEBUG, "%s: enable=%d", __func__, enabled); 251 252 ret += nss_macsec_secy_controlled_port_en_set(drv->secy_id, enabled); 253 254 return ret; 255 } 256 257 258 static int macsec_qca_lookup_channel(struct channel_map *map, 259 struct ieee802_1x_mka_sci *sci, 260 u32 *channel) 261 { 262 u32 i; 263 264 for (i = 0; i < MAXSC; i++) { 265 if (os_memcmp(&map[i].sci, sci, 266 sizeof(struct ieee802_1x_mka_sci)) == 0) { 267 *channel = i; 268 return 0; 269 } 270 } 271 272 return -1; 273 } 274 275 276 static void macsec_qca_register_channel(struct channel_map *map, 277 struct ieee802_1x_mka_sci *sci, 278 u32 channel) 279 { 280 os_memcpy(&map[channel].sci, sci, sizeof(struct ieee802_1x_mka_sci)); 281 } 282 283 284 static int macsec_qca_lookup_receive_channel(struct macsec_qca_data *drv, 285 struct receive_sc *sc, 286 u32 *channel) 287 { 288 return macsec_qca_lookup_channel(drv->receive_channel_map, &sc->sci, 289 channel); 290 } 291 292 293 static void macsec_qca_register_receive_channel(struct macsec_qca_data *drv, 294 struct receive_sc *sc, 295 u32 channel) 296 { 297 macsec_qca_register_channel(drv->receive_channel_map, &sc->sci, 298 channel); 299 } 300 301 302 static int macsec_qca_lookup_transmit_channel(struct macsec_qca_data *drv, 303 struct transmit_sc *sc, 304 u32 *channel) 305 { 306 return macsec_qca_lookup_channel(drv->transmit_channel_map, &sc->sci, 307 channel); 308 } 309 310 311 static void macsec_qca_register_transmit_channel(struct macsec_qca_data *drv, 312 struct transmit_sc *sc, 313 u32 channel) 314 { 315 macsec_qca_register_channel(drv->transmit_channel_map, &sc->sci, 316 channel); 317 } 318 319 320 static int macsec_qca_get_receive_lowest_pn(void *priv, struct receive_sa *sa) 321 { 322 struct macsec_qca_data *drv = priv; 323 int ret = 0; 324 u32 next_pn = 0; 325 bool enabled = FALSE; 326 u32 win; 327 u32 channel; 328 329 ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel); 330 if (ret != 0) 331 return ret; 332 333 ret += nss_macsec_secy_rx_sa_next_pn_get(drv->secy_id, channel, sa->an, 334 &next_pn); 335 ret += nss_macsec_secy_rx_sc_replay_protect_get(drv->secy_id, channel, 336 &enabled); 337 ret += nss_macsec_secy_rx_sc_anti_replay_window_get(drv->secy_id, 338 channel, &win); 339 340 if (enabled) 341 sa->lowest_pn = (next_pn > win) ? (next_pn - win) : 1; 342 else 343 sa->lowest_pn = next_pn; 344 345 wpa_printf(MSG_DEBUG, "%s: lpn=0x%x", __func__, sa->lowest_pn); 346 347 return ret; 348 } 349 350 351 static int macsec_qca_get_transmit_next_pn(void *priv, struct transmit_sa *sa) 352 { 353 struct macsec_qca_data *drv = priv; 354 int ret = 0; 355 u32 channel; 356 357 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel); 358 if (ret != 0) 359 return ret; 360 361 ret += nss_macsec_secy_tx_sa_next_pn_get(drv->secy_id, channel, sa->an, 362 &sa->next_pn); 363 364 wpa_printf(MSG_DEBUG, "%s: npn=0x%x", __func__, sa->next_pn); 365 366 return ret; 367 } 368 369 370 int macsec_qca_set_transmit_next_pn(void *priv, struct transmit_sa *sa) 371 { 372 struct macsec_qca_data *drv = priv; 373 int ret = 0; 374 u32 channel; 375 376 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel); 377 if (ret != 0) 378 return ret; 379 380 ret += nss_macsec_secy_tx_sa_next_pn_set(drv->secy_id, channel, sa->an, 381 sa->next_pn); 382 383 wpa_printf(MSG_INFO, "%s: npn=0x%x", __func__, sa->next_pn); 384 385 return ret; 386 } 387 388 389 static int macsec_qca_get_available_receive_sc(void *priv, u32 *channel) 390 { 391 struct macsec_qca_data *drv = priv; 392 int ret = 0; 393 u32 sc_ch = 0; 394 bool in_use = FALSE; 395 396 for (sc_ch = 0; sc_ch < MAXSC; sc_ch++) { 397 ret = nss_macsec_secy_rx_sc_in_used_get(drv->secy_id, sc_ch, 398 &in_use); 399 if (ret) 400 continue; 401 402 if (!in_use) { 403 *channel = sc_ch; 404 wpa_printf(MSG_DEBUG, "%s: channel=%d", 405 __func__, *channel); 406 return 0; 407 } 408 } 409 410 wpa_printf(MSG_DEBUG, "%s: no available channel", __func__); 411 412 return -1; 413 } 414 415 416 static int macsec_qca_create_receive_sc(void *priv, struct receive_sc *sc, 417 unsigned int conf_offset, 418 int validation) 419 { 420 struct macsec_qca_data *drv = priv; 421 int ret = 0; 422 fal_rx_prc_lut_t entry; 423 fal_rx_sc_validate_frame_e vf; 424 enum validate_frames validate_frames = validation; 425 u32 channel; 426 const u8 *sci_addr = sc->sci.addr; 427 u16 sci_port = be_to_host16(sc->sci.port); 428 429 ret = macsec_qca_get_available_receive_sc(priv, &channel); 430 if (ret != 0) 431 return ret; 432 433 wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel); 434 435 /* rx prc lut */ 436 os_memset(&entry, 0, sizeof(entry)); 437 438 os_memcpy(entry.sci, sci_addr, ETH_ALEN); 439 entry.sci[6] = (sci_port >> 8) & 0xf; 440 entry.sci[7] = sci_port & 0xf; 441 entry.sci_mask = 0xf; 442 443 entry.valid = 1; 444 entry.channel = channel; 445 entry.action = FAL_RX_PRC_ACTION_PROCESS; 446 entry.offset = conf_offset; 447 448 /* rx validate frame */ 449 if (validate_frames == Strict) 450 vf = FAL_RX_SC_VALIDATE_FRAME_STRICT; 451 else if (validate_frames == Checked) 452 vf = FAL_RX_SC_VALIDATE_FRAME_CHECK; 453 else 454 vf = FAL_RX_SC_VALIDATE_FRAME_DISABLED; 455 456 ret += nss_macsec_secy_rx_prc_lut_set(drv->secy_id, channel, &entry); 457 ret += nss_macsec_secy_rx_sc_create(drv->secy_id, channel); 458 ret += nss_macsec_secy_rx_sc_validate_frame_set(drv->secy_id, channel, 459 vf); 460 ret += nss_macsec_secy_rx_sc_replay_protect_set(drv->secy_id, channel, 461 drv->replay_protect); 462 ret += nss_macsec_secy_rx_sc_anti_replay_window_set(drv->secy_id, 463 channel, 464 drv->replay_window); 465 466 macsec_qca_register_receive_channel(drv, sc, channel); 467 468 return ret; 469 } 470 471 472 static int macsec_qca_delete_receive_sc(void *priv, struct receive_sc *sc) 473 { 474 struct macsec_qca_data *drv = priv; 475 int ret; 476 fal_rx_prc_lut_t entry; 477 u32 channel; 478 479 ret = macsec_qca_lookup_receive_channel(priv, sc, &channel); 480 if (ret != 0) 481 return ret; 482 483 wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel); 484 485 /* rx prc lut */ 486 os_memset(&entry, 0, sizeof(entry)); 487 488 ret += nss_macsec_secy_rx_sc_del(drv->secy_id, channel); 489 ret += nss_macsec_secy_rx_prc_lut_set(drv->secy_id, channel, &entry); 490 491 return ret; 492 } 493 494 495 static int macsec_qca_create_receive_sa(void *priv, struct receive_sa *sa) 496 { 497 struct macsec_qca_data *drv = priv; 498 int ret; 499 fal_rx_sak_t rx_sak; 500 int i = 0; 501 u32 channel; 502 503 ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel); 504 if (ret != 0) 505 return ret; 506 507 wpa_printf(MSG_DEBUG, "%s, channel=%d, an=%d, lpn=0x%x", 508 __func__, channel, sa->an, sa->lowest_pn); 509 510 os_memset(&rx_sak, 0, sizeof(rx_sak)); 511 for (i = 0; i < 16; i++) 512 rx_sak.sak[i] = sa->pkey->key[15 - i]; 513 514 ret += nss_macsec_secy_rx_sa_create(drv->secy_id, channel, sa->an); 515 ret += nss_macsec_secy_rx_sak_set(drv->secy_id, channel, sa->an, 516 &rx_sak); 517 518 return ret; 519 } 520 521 522 static int macsec_qca_enable_receive_sa(void *priv, struct receive_sa *sa) 523 { 524 struct macsec_qca_data *drv = priv; 525 int ret; 526 u32 channel; 527 528 ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel); 529 if (ret != 0) 530 return ret; 531 532 wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel, 533 sa->an); 534 535 ret += nss_macsec_secy_rx_sa_en_set(drv->secy_id, channel, sa->an, 536 TRUE); 537 538 return ret; 539 } 540 541 542 static int macsec_qca_disable_receive_sa(void *priv, struct receive_sa *sa) 543 { 544 struct macsec_qca_data *drv = priv; 545 int ret; 546 u32 channel; 547 548 ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel); 549 if (ret != 0) 550 return ret; 551 552 wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel, 553 sa->an); 554 555 ret += nss_macsec_secy_rx_sa_en_set(drv->secy_id, channel, sa->an, 556 FALSE); 557 558 return ret; 559 } 560 561 562 static int macsec_qca_get_available_transmit_sc(void *priv, u32 *channel) 563 { 564 struct macsec_qca_data *drv = priv; 565 u32 sc_ch = 0; 566 bool in_use = FALSE; 567 568 for (sc_ch = 0; sc_ch < MAXSC; sc_ch++) { 569 if (nss_macsec_secy_tx_sc_in_used_get(drv->secy_id, sc_ch, 570 &in_use)) 571 continue; 572 573 if (!in_use) { 574 *channel = sc_ch; 575 wpa_printf(MSG_DEBUG, "%s: channel=%d", 576 __func__, *channel); 577 return 0; 578 } 579 } 580 581 wpa_printf(MSG_DEBUG, "%s: no avaiable channel", __func__); 582 583 return -1; 584 } 585 586 587 static int macsec_qca_create_transmit_sc(void *priv, struct transmit_sc *sc, 588 unsigned int conf_offset) 589 { 590 struct macsec_qca_data *drv = priv; 591 int ret; 592 fal_tx_class_lut_t entry; 593 u8 psci[ETH_ALEN + 2]; 594 u32 channel; 595 596 ret = macsec_qca_get_available_transmit_sc(priv, &channel); 597 if (ret != 0) 598 return ret; 599 600 wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel); 601 602 /* class lut */ 603 os_memset(&entry, 0, sizeof(entry)); 604 605 entry.valid = 1; 606 entry.action = FAL_TX_CLASS_ACTION_FORWARD; 607 entry.channel = channel; 608 609 os_memcpy(psci, sc->sci.addr, ETH_ALEN); 610 psci[6] = (sc->sci.port >> 8) & 0xf; 611 psci[7] = sc->sci.port & 0xf; 612 613 ret += nss_macsec_secy_tx_class_lut_set(drv->secy_id, channel, &entry); 614 ret += nss_macsec_secy_tx_sc_create(drv->secy_id, channel, psci, 8); 615 ret += nss_macsec_secy_tx_sc_protect_set(drv->secy_id, channel, 616 drv->protect_frames); 617 ret += nss_macsec_secy_tx_sc_confidentiality_offset_set(drv->secy_id, 618 channel, 619 conf_offset); 620 621 macsec_qca_register_transmit_channel(drv, sc, channel); 622 623 return ret; 624 } 625 626 627 static int macsec_qca_delete_transmit_sc(void *priv, struct transmit_sc *sc) 628 { 629 struct macsec_qca_data *drv = priv; 630 int ret; 631 fal_tx_class_lut_t entry; 632 u32 channel; 633 634 ret = macsec_qca_lookup_transmit_channel(priv, sc, &channel); 635 if (ret != 0) 636 return ret; 637 638 wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel); 639 640 /* class lut */ 641 os_memset(&entry, 0, sizeof(entry)); 642 643 ret += nss_macsec_secy_tx_class_lut_set(drv->secy_id, channel, &entry); 644 ret += nss_macsec_secy_tx_sc_del(drv->secy_id, channel); 645 646 return ret; 647 } 648 649 650 static int macsec_qca_create_transmit_sa(void *priv, struct transmit_sa *sa) 651 { 652 struct macsec_qca_data *drv = priv; 653 int ret; 654 u8 tci = 0; 655 fal_tx_sak_t tx_sak; 656 int i; 657 u32 channel; 658 659 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel); 660 if (ret != 0) 661 return ret; 662 663 wpa_printf(MSG_DEBUG, 664 "%s: channel=%d, an=%d, next_pn=0x%x, confidentiality=%d", 665 __func__, channel, sa->an, sa->next_pn, sa->confidentiality); 666 667 if (drv->always_include_sci) 668 tci |= TCI_SC; 669 else if (drv->use_es) 670 tci |= TCI_ES; 671 else if (drv->use_scb) 672 tci |= TCI_SCB; 673 674 if (sa->confidentiality) 675 tci |= TCI_E | TCI_C; 676 677 os_memset(&tx_sak, 0, sizeof(tx_sak)); 678 for (i = 0; i < 16; i++) 679 tx_sak.sak[i] = sa->pkey->key[15 - i]; 680 681 ret += nss_macsec_secy_tx_sa_next_pn_set(drv->secy_id, channel, sa->an, 682 sa->next_pn); 683 ret += nss_macsec_secy_tx_sak_set(drv->secy_id, channel, sa->an, 684 &tx_sak); 685 ret += nss_macsec_secy_tx_sc_tci_7_2_set(drv->secy_id, channel, 686 (tci >> 2)); 687 ret += nss_macsec_secy_tx_sc_an_set(drv->secy_id, channel, sa->an); 688 689 return ret; 690 } 691 692 693 static int macsec_qca_enable_transmit_sa(void *priv, struct transmit_sa *sa) 694 { 695 struct macsec_qca_data *drv = priv; 696 int ret; 697 u32 channel; 698 699 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel); 700 if (ret != 0) 701 return ret; 702 703 wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel, 704 sa->an); 705 706 ret += nss_macsec_secy_tx_sa_en_set(drv->secy_id, channel, sa->an, 707 TRUE); 708 709 return ret; 710 } 711 712 713 static int macsec_qca_disable_transmit_sa(void *priv, struct transmit_sa *sa) 714 { 715 struct macsec_qca_data *drv = priv; 716 int ret; 717 u32 channel; 718 719 ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel); 720 if (ret != 0) 721 return ret; 722 723 wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel, 724 sa->an); 725 726 ret += nss_macsec_secy_tx_sa_en_set(drv->secy_id, channel, sa->an, 727 FALSE); 728 729 return ret; 730 } 731 732 733 const struct wpa_driver_ops wpa_driver_macsec_qca_ops = { 734 .name = "macsec_qca", 735 .desc = "QCA MACsec Ethernet driver", 736 .get_ssid = driver_wired_get_ssid, 737 .get_bssid = driver_wired_get_bssid, 738 .get_capa = driver_wired_get_capa, 739 .init = macsec_qca_init, 740 .deinit = macsec_qca_deinit, 741 742 .macsec_init = macsec_qca_macsec_init, 743 .macsec_deinit = macsec_qca_macsec_deinit, 744 .macsec_get_capability = macsec_qca_get_capability, 745 .enable_protect_frames = macsec_qca_enable_protect_frames, 746 .set_replay_protect = macsec_qca_set_replay_protect, 747 .set_current_cipher_suite = macsec_qca_set_current_cipher_suite, 748 .enable_controlled_port = macsec_qca_enable_controlled_port, 749 .get_receive_lowest_pn = macsec_qca_get_receive_lowest_pn, 750 .get_transmit_next_pn = macsec_qca_get_transmit_next_pn, 751 .set_transmit_next_pn = macsec_qca_set_transmit_next_pn, 752 .create_receive_sc = macsec_qca_create_receive_sc, 753 .delete_receive_sc = macsec_qca_delete_receive_sc, 754 .create_receive_sa = macsec_qca_create_receive_sa, 755 .enable_receive_sa = macsec_qca_enable_receive_sa, 756 .disable_receive_sa = macsec_qca_disable_receive_sa, 757 .create_transmit_sc = macsec_qca_create_transmit_sc, 758 .delete_transmit_sc = macsec_qca_delete_transmit_sc, 759 .create_transmit_sa = macsec_qca_create_transmit_sa, 760 .enable_transmit_sa = macsec_qca_enable_transmit_sa, 761 .disable_transmit_sa = macsec_qca_disable_transmit_sa, 762 }; 763