15b9c547cSRui Paulo /* 25b9c547cSRui Paulo * Wired Ethernet driver interface for QCA MACsec driver 35b9c547cSRui Paulo * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi> 45b9c547cSRui Paulo * Copyright (c) 2004, Gunter Burchardt <tira@isx.de> 55b9c547cSRui Paulo * Copyright (c) 2013-2014, Qualcomm Atheros, Inc. 65b9c547cSRui Paulo * 75b9c547cSRui Paulo * This software may be distributed under the terms of the BSD license. 85b9c547cSRui Paulo * See README for more details. 95b9c547cSRui Paulo */ 105b9c547cSRui Paulo 115b9c547cSRui Paulo #include "includes.h" 125b9c547cSRui Paulo #include <sys/ioctl.h> 135b9c547cSRui Paulo #include <net/if.h> 14780fb4a2SCy Schubert #include <inttypes.h> 155b9c547cSRui Paulo #ifdef __linux__ 165b9c547cSRui Paulo #include <netpacket/packet.h> 175b9c547cSRui Paulo #include <net/if_arp.h> 185b9c547cSRui Paulo #include <net/if.h> 195b9c547cSRui Paulo #endif /* __linux__ */ 205b9c547cSRui Paulo #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) 215b9c547cSRui Paulo #include <net/if_dl.h> 225b9c547cSRui Paulo #include <net/if_media.h> 235b9c547cSRui Paulo #endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) */ 245b9c547cSRui Paulo #ifdef __sun__ 255b9c547cSRui Paulo #include <sys/sockio.h> 265b9c547cSRui Paulo #endif /* __sun__ */ 275b9c547cSRui Paulo 285b9c547cSRui Paulo #include "utils/common.h" 295b9c547cSRui Paulo #include "utils/eloop.h" 305b9c547cSRui Paulo #include "common/defs.h" 315b9c547cSRui Paulo #include "common/ieee802_1x_defs.h" 32*85732ac8SCy Schubert #include "pae/ieee802_1x_kay.h" 335b9c547cSRui Paulo #include "driver.h" 34*85732ac8SCy Schubert #include "driver_wired_common.h" 355b9c547cSRui Paulo 365b9c547cSRui Paulo #include "nss_macsec_secy.h" 375b9c547cSRui Paulo #include "nss_macsec_secy_rx.h" 385b9c547cSRui Paulo #include "nss_macsec_secy_tx.h" 395b9c547cSRui Paulo 405b9c547cSRui Paulo #define MAXSC 16 415b9c547cSRui Paulo 42*85732ac8SCy Schubert #define SAK_128_LEN 16 43*85732ac8SCy Schubert #define SAK_256_LEN 32 44*85732ac8SCy Schubert 455b9c547cSRui Paulo /* TCI field definition */ 465b9c547cSRui Paulo #define TCI_ES 0x40 475b9c547cSRui Paulo #define TCI_SC 0x20 485b9c547cSRui Paulo #define TCI_SCB 0x10 495b9c547cSRui Paulo #define TCI_E 0x08 505b9c547cSRui Paulo #define TCI_C 0x04 515b9c547cSRui Paulo 525b9c547cSRui Paulo #ifdef _MSC_VER 535b9c547cSRui Paulo #pragma pack(push, 1) 545b9c547cSRui Paulo #endif /* _MSC_VER */ 555b9c547cSRui Paulo 565b9c547cSRui Paulo #ifdef _MSC_VER 575b9c547cSRui Paulo #pragma pack(pop) 585b9c547cSRui Paulo #endif /* _MSC_VER */ 595b9c547cSRui Paulo 60*85732ac8SCy Schubert struct channel_map { 61*85732ac8SCy Schubert struct ieee802_1x_mka_sci sci; 62*85732ac8SCy Schubert }; 635b9c547cSRui Paulo 645b9c547cSRui Paulo struct macsec_qca_data { 65*85732ac8SCy Schubert struct driver_wired_common_data common; 665b9c547cSRui Paulo 67*85732ac8SCy Schubert u32 secy_id; 685b9c547cSRui Paulo 695b9c547cSRui Paulo /* shadow */ 705b9c547cSRui Paulo Boolean always_include_sci; 715b9c547cSRui Paulo Boolean use_es; 725b9c547cSRui Paulo Boolean use_scb; 735b9c547cSRui Paulo Boolean protect_frames; 745b9c547cSRui Paulo Boolean replay_protect; 755b9c547cSRui Paulo u32 replay_window; 76*85732ac8SCy Schubert 77*85732ac8SCy Schubert struct channel_map receive_channel_map[MAXSC]; 78*85732ac8SCy Schubert struct channel_map transmit_channel_map[MAXSC]; 795b9c547cSRui Paulo }; 805b9c547cSRui Paulo 815b9c547cSRui Paulo 825b9c547cSRui Paulo static void __macsec_drv_init(struct macsec_qca_data *drv) 835b9c547cSRui Paulo { 845b9c547cSRui Paulo int ret = 0; 855b9c547cSRui Paulo fal_rx_ctl_filt_t rx_ctl_filt; 865b9c547cSRui Paulo fal_tx_ctl_filt_t tx_ctl_filt; 875b9c547cSRui Paulo 885b9c547cSRui Paulo wpa_printf(MSG_INFO, "%s: secy_id=%d", __func__, drv->secy_id); 895b9c547cSRui Paulo 905b9c547cSRui Paulo /* Enable Secy and Let EAPoL bypass */ 915b9c547cSRui Paulo ret = nss_macsec_secy_en_set(drv->secy_id, TRUE); 925b9c547cSRui Paulo if (ret) 935b9c547cSRui Paulo wpa_printf(MSG_ERROR, "nss_macsec_secy_en_set: FAIL"); 945b9c547cSRui Paulo 955b9c547cSRui Paulo ret = nss_macsec_secy_sc_sa_mapping_mode_set(drv->secy_id, 965b9c547cSRui Paulo FAL_SC_SA_MAP_1_4); 975b9c547cSRui Paulo if (ret) 985b9c547cSRui Paulo wpa_printf(MSG_ERROR, 995b9c547cSRui Paulo "nss_macsec_secy_sc_sa_mapping_mode_set: FAIL"); 1005b9c547cSRui Paulo 1015b9c547cSRui Paulo os_memset(&rx_ctl_filt, 0, sizeof(rx_ctl_filt)); 1025b9c547cSRui Paulo rx_ctl_filt.bypass = 1; 1035b9c547cSRui Paulo rx_ctl_filt.match_type = IG_CTL_COMPARE_ETHER_TYPE; 1045b9c547cSRui Paulo rx_ctl_filt.match_mask = 0xffff; 1055b9c547cSRui Paulo rx_ctl_filt.ether_type_da_range = 0x888e; 1065b9c547cSRui Paulo ret = nss_macsec_secy_rx_ctl_filt_set(drv->secy_id, 0, &rx_ctl_filt); 1075b9c547cSRui Paulo if (ret) 1085b9c547cSRui Paulo wpa_printf(MSG_ERROR, "nss_macsec_secy_rx_ctl_filt_set: FAIL"); 1095b9c547cSRui Paulo 1105b9c547cSRui Paulo os_memset(&tx_ctl_filt, 0, sizeof(tx_ctl_filt)); 1115b9c547cSRui Paulo tx_ctl_filt.bypass = 1; 1125b9c547cSRui Paulo tx_ctl_filt.match_type = EG_CTL_COMPARE_ETHER_TYPE; 1135b9c547cSRui Paulo tx_ctl_filt.match_mask = 0xffff; 1145b9c547cSRui Paulo tx_ctl_filt.ether_type_da_range = 0x888e; 1155b9c547cSRui Paulo ret = nss_macsec_secy_tx_ctl_filt_set(drv->secy_id, 0, &tx_ctl_filt); 1165b9c547cSRui Paulo if (ret) 1175b9c547cSRui Paulo wpa_printf(MSG_ERROR, "nss_macsec_secy_tx_ctl_filt_set: FAIL"); 1185b9c547cSRui Paulo } 1195b9c547cSRui Paulo 1205b9c547cSRui Paulo 1215b9c547cSRui Paulo static void __macsec_drv_deinit(struct macsec_qca_data *drv) 1225b9c547cSRui Paulo { 1235b9c547cSRui Paulo nss_macsec_secy_en_set(drv->secy_id, FALSE); 1245b9c547cSRui Paulo nss_macsec_secy_rx_sc_del_all(drv->secy_id); 1255b9c547cSRui Paulo nss_macsec_secy_tx_sc_del_all(drv->secy_id); 1265b9c547cSRui Paulo } 1275b9c547cSRui Paulo 1285b9c547cSRui Paulo 1295b9c547cSRui Paulo static void * macsec_qca_init(void *ctx, const char *ifname) 1305b9c547cSRui Paulo { 1315b9c547cSRui Paulo struct macsec_qca_data *drv; 1325b9c547cSRui Paulo 1335b9c547cSRui Paulo drv = os_zalloc(sizeof(*drv)); 1345b9c547cSRui Paulo if (drv == NULL) 1355b9c547cSRui Paulo return NULL; 1365b9c547cSRui Paulo 1375b9c547cSRui Paulo /* Board specific settings */ 138*85732ac8SCy Schubert if (os_memcmp("eth2", ifname, 4) == 0) 1395b9c547cSRui Paulo drv->secy_id = 1; 140*85732ac8SCy Schubert else if (os_memcmp("eth3", ifname, 4) == 0) 1415b9c547cSRui Paulo drv->secy_id = 2; 1425b9c547cSRui Paulo else 1435b9c547cSRui Paulo drv->secy_id = -1; 1445b9c547cSRui Paulo 145*85732ac8SCy Schubert if (driver_wired_init_common(&drv->common, ifname, ctx) < 0) { 1465b9c547cSRui Paulo os_free(drv); 1475b9c547cSRui Paulo return NULL; 1485b9c547cSRui Paulo } 1495b9c547cSRui Paulo 1505b9c547cSRui Paulo return drv; 1515b9c547cSRui Paulo } 1525b9c547cSRui Paulo 1535b9c547cSRui Paulo 1545b9c547cSRui Paulo static void macsec_qca_deinit(void *priv) 1555b9c547cSRui Paulo { 1565b9c547cSRui Paulo struct macsec_qca_data *drv = priv; 1575b9c547cSRui Paulo 158*85732ac8SCy Schubert driver_wired_deinit_common(&drv->common); 1595b9c547cSRui Paulo os_free(drv); 1605b9c547cSRui Paulo } 1615b9c547cSRui Paulo 1625b9c547cSRui Paulo 1635b9c547cSRui Paulo static int macsec_qca_macsec_init(void *priv, struct macsec_init_params *params) 1645b9c547cSRui Paulo { 1655b9c547cSRui Paulo struct macsec_qca_data *drv = priv; 1665b9c547cSRui Paulo 1675b9c547cSRui Paulo drv->always_include_sci = params->always_include_sci; 1685b9c547cSRui Paulo drv->use_es = params->use_es; 1695b9c547cSRui Paulo drv->use_scb = params->use_scb; 1705b9c547cSRui Paulo 1715b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "%s: es=%d, scb=%d, sci=%d", 1725b9c547cSRui Paulo __func__, drv->use_es, drv->use_scb, 1735b9c547cSRui Paulo drv->always_include_sci); 1745b9c547cSRui Paulo 1755b9c547cSRui Paulo __macsec_drv_init(drv); 1765b9c547cSRui Paulo 1775b9c547cSRui Paulo return 0; 1785b9c547cSRui Paulo } 1795b9c547cSRui Paulo 1805b9c547cSRui Paulo 1815b9c547cSRui Paulo static int macsec_qca_macsec_deinit(void *priv) 1825b9c547cSRui Paulo { 1835b9c547cSRui Paulo struct macsec_qca_data *drv = priv; 1845b9c547cSRui Paulo 1855b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "%s", __func__); 1865b9c547cSRui Paulo 1875b9c547cSRui Paulo __macsec_drv_deinit(drv); 1885b9c547cSRui Paulo 1895b9c547cSRui Paulo return 0; 1905b9c547cSRui Paulo } 1915b9c547cSRui Paulo 1925b9c547cSRui Paulo 193*85732ac8SCy Schubert static int macsec_qca_get_capability(void *priv, enum macsec_cap *cap) 194*85732ac8SCy Schubert { 195*85732ac8SCy Schubert wpa_printf(MSG_DEBUG, "%s", __func__); 196*85732ac8SCy Schubert 197*85732ac8SCy Schubert *cap = MACSEC_CAP_INTEG_AND_CONF_0_30_50; 198*85732ac8SCy Schubert 199*85732ac8SCy Schubert return 0; 200*85732ac8SCy Schubert } 201*85732ac8SCy Schubert 202*85732ac8SCy Schubert 2035b9c547cSRui Paulo static int macsec_qca_enable_protect_frames(void *priv, Boolean enabled) 2045b9c547cSRui Paulo { 2055b9c547cSRui Paulo struct macsec_qca_data *drv = priv; 2065b9c547cSRui Paulo int ret = 0; 2075b9c547cSRui Paulo 2085b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); 2095b9c547cSRui Paulo 2105b9c547cSRui Paulo drv->protect_frames = enabled; 2115b9c547cSRui Paulo 2125b9c547cSRui Paulo return ret; 2135b9c547cSRui Paulo } 2145b9c547cSRui Paulo 2155b9c547cSRui Paulo 2165b9c547cSRui Paulo static int macsec_qca_set_replay_protect(void *priv, Boolean enabled, 2175b9c547cSRui Paulo unsigned int window) 2185b9c547cSRui Paulo { 2195b9c547cSRui Paulo struct macsec_qca_data *drv = priv; 2205b9c547cSRui Paulo int ret = 0; 2215b9c547cSRui Paulo 2225b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "%s: enabled=%d, win=%u", 2235b9c547cSRui Paulo __func__, enabled, window); 2245b9c547cSRui Paulo 2255b9c547cSRui Paulo drv->replay_protect = enabled; 2265b9c547cSRui Paulo drv->replay_window = window; 2275b9c547cSRui Paulo 2285b9c547cSRui Paulo return ret; 2295b9c547cSRui Paulo } 2305b9c547cSRui Paulo 2315b9c547cSRui Paulo 232*85732ac8SCy Schubert static fal_cipher_suite_e macsec_qca_cs_type_get(u64 cs) 233*85732ac8SCy Schubert { 234*85732ac8SCy Schubert if (cs == CS_ID_GCM_AES_128) 235*85732ac8SCy Schubert return FAL_CIPHER_SUITE_AES_GCM_128; 236*85732ac8SCy Schubert if (cs == CS_ID_GCM_AES_256) 237*85732ac8SCy Schubert return FAL_CIPHER_SUITE_AES_GCM_256; 238*85732ac8SCy Schubert return FAL_CIPHER_SUITE_MAX; 239*85732ac8SCy Schubert } 240*85732ac8SCy Schubert 241*85732ac8SCy Schubert 242780fb4a2SCy Schubert static int macsec_qca_set_current_cipher_suite(void *priv, u64 cs) 2435b9c547cSRui Paulo { 244*85732ac8SCy Schubert struct macsec_qca_data *drv = priv; 245*85732ac8SCy Schubert fal_cipher_suite_e cs_type; 246*85732ac8SCy Schubert 247*85732ac8SCy Schubert if (cs != CS_ID_GCM_AES_128 && cs != CS_ID_GCM_AES_256) { 248780fb4a2SCy Schubert wpa_printf(MSG_ERROR, 249780fb4a2SCy Schubert "%s: NOT supported CipherSuite: %016" PRIx64, 250780fb4a2SCy Schubert __func__, cs); 2515b9c547cSRui Paulo return -1; 2525b9c547cSRui Paulo } 2535b9c547cSRui Paulo 254*85732ac8SCy Schubert wpa_printf(MSG_DEBUG, "%s: CipherSuite: %016" PRIx64, __func__, cs); 2555b9c547cSRui Paulo 256*85732ac8SCy Schubert cs_type = macsec_qca_cs_type_get(cs); 257*85732ac8SCy Schubert return nss_macsec_secy_cipher_suite_set(drv->secy_id, cs_type); 2585b9c547cSRui Paulo } 2595b9c547cSRui Paulo 2605b9c547cSRui Paulo 2615b9c547cSRui Paulo static int macsec_qca_enable_controlled_port(void *priv, Boolean enabled) 2625b9c547cSRui Paulo { 2635b9c547cSRui Paulo struct macsec_qca_data *drv = priv; 2645b9c547cSRui Paulo int ret = 0; 2655b9c547cSRui Paulo 2665b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "%s: enable=%d", __func__, enabled); 2675b9c547cSRui Paulo 2685b9c547cSRui Paulo ret += nss_macsec_secy_controlled_port_en_set(drv->secy_id, enabled); 2695b9c547cSRui Paulo 2705b9c547cSRui Paulo return ret; 2715b9c547cSRui Paulo } 2725b9c547cSRui Paulo 2735b9c547cSRui Paulo 274*85732ac8SCy Schubert static int macsec_qca_lookup_channel(struct channel_map *map, 275*85732ac8SCy Schubert struct ieee802_1x_mka_sci *sci, 276*85732ac8SCy Schubert u32 *channel) 277*85732ac8SCy Schubert { 278*85732ac8SCy Schubert u32 i; 279*85732ac8SCy Schubert 280*85732ac8SCy Schubert for (i = 0; i < MAXSC; i++) { 281*85732ac8SCy Schubert if (os_memcmp(&map[i].sci, sci, 282*85732ac8SCy Schubert sizeof(struct ieee802_1x_mka_sci)) == 0) { 283*85732ac8SCy Schubert *channel = i; 284*85732ac8SCy Schubert return 0; 285*85732ac8SCy Schubert } 286*85732ac8SCy Schubert } 287*85732ac8SCy Schubert 288*85732ac8SCy Schubert return -1; 289*85732ac8SCy Schubert } 290*85732ac8SCy Schubert 291*85732ac8SCy Schubert 292*85732ac8SCy Schubert static void macsec_qca_register_channel(struct channel_map *map, 293*85732ac8SCy Schubert struct ieee802_1x_mka_sci *sci, 294*85732ac8SCy Schubert u32 channel) 295*85732ac8SCy Schubert { 296*85732ac8SCy Schubert os_memcpy(&map[channel].sci, sci, sizeof(struct ieee802_1x_mka_sci)); 297*85732ac8SCy Schubert } 298*85732ac8SCy Schubert 299*85732ac8SCy Schubert 300*85732ac8SCy Schubert static int macsec_qca_lookup_receive_channel(struct macsec_qca_data *drv, 301*85732ac8SCy Schubert struct receive_sc *sc, 302*85732ac8SCy Schubert u32 *channel) 303*85732ac8SCy Schubert { 304*85732ac8SCy Schubert return macsec_qca_lookup_channel(drv->receive_channel_map, &sc->sci, 305*85732ac8SCy Schubert channel); 306*85732ac8SCy Schubert } 307*85732ac8SCy Schubert 308*85732ac8SCy Schubert 309*85732ac8SCy Schubert static void macsec_qca_register_receive_channel(struct macsec_qca_data *drv, 310*85732ac8SCy Schubert struct receive_sc *sc, 311*85732ac8SCy Schubert u32 channel) 312*85732ac8SCy Schubert { 313*85732ac8SCy Schubert macsec_qca_register_channel(drv->receive_channel_map, &sc->sci, 314*85732ac8SCy Schubert channel); 315*85732ac8SCy Schubert } 316*85732ac8SCy Schubert 317*85732ac8SCy Schubert 318*85732ac8SCy Schubert static int macsec_qca_lookup_transmit_channel(struct macsec_qca_data *drv, 319*85732ac8SCy Schubert struct transmit_sc *sc, 320*85732ac8SCy Schubert u32 *channel) 321*85732ac8SCy Schubert { 322*85732ac8SCy Schubert return macsec_qca_lookup_channel(drv->transmit_channel_map, &sc->sci, 323*85732ac8SCy Schubert channel); 324*85732ac8SCy Schubert } 325*85732ac8SCy Schubert 326*85732ac8SCy Schubert 327*85732ac8SCy Schubert static void macsec_qca_register_transmit_channel(struct macsec_qca_data *drv, 328*85732ac8SCy Schubert struct transmit_sc *sc, 329*85732ac8SCy Schubert u32 channel) 330*85732ac8SCy Schubert { 331*85732ac8SCy Schubert macsec_qca_register_channel(drv->transmit_channel_map, &sc->sci, 332*85732ac8SCy Schubert channel); 333*85732ac8SCy Schubert } 334*85732ac8SCy Schubert 335*85732ac8SCy Schubert 336*85732ac8SCy Schubert static int macsec_qca_get_receive_lowest_pn(void *priv, struct receive_sa *sa) 3375b9c547cSRui Paulo { 3385b9c547cSRui Paulo struct macsec_qca_data *drv = priv; 3395b9c547cSRui Paulo int ret = 0; 3405b9c547cSRui Paulo u32 next_pn = 0; 3415b9c547cSRui Paulo bool enabled = FALSE; 3425b9c547cSRui Paulo u32 win; 343*85732ac8SCy Schubert u32 channel; 3445b9c547cSRui Paulo 345*85732ac8SCy Schubert ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel); 346*85732ac8SCy Schubert if (ret != 0) 347*85732ac8SCy Schubert return ret; 348*85732ac8SCy Schubert 349*85732ac8SCy Schubert ret += nss_macsec_secy_rx_sa_next_pn_get(drv->secy_id, channel, sa->an, 3505b9c547cSRui Paulo &next_pn); 3515b9c547cSRui Paulo ret += nss_macsec_secy_rx_sc_replay_protect_get(drv->secy_id, channel, 3525b9c547cSRui Paulo &enabled); 3535b9c547cSRui Paulo ret += nss_macsec_secy_rx_sc_anti_replay_window_get(drv->secy_id, 3545b9c547cSRui Paulo channel, &win); 3555b9c547cSRui Paulo 3565b9c547cSRui Paulo if (enabled) 357*85732ac8SCy Schubert sa->lowest_pn = (next_pn > win) ? (next_pn - win) : 1; 3585b9c547cSRui Paulo else 359*85732ac8SCy Schubert sa->lowest_pn = next_pn; 3605b9c547cSRui Paulo 361*85732ac8SCy Schubert wpa_printf(MSG_DEBUG, "%s: lpn=0x%x", __func__, sa->lowest_pn); 3625b9c547cSRui Paulo 3635b9c547cSRui Paulo return ret; 3645b9c547cSRui Paulo } 3655b9c547cSRui Paulo 3665b9c547cSRui Paulo 367*85732ac8SCy Schubert static int macsec_qca_get_transmit_next_pn(void *priv, struct transmit_sa *sa) 3685b9c547cSRui Paulo { 3695b9c547cSRui Paulo struct macsec_qca_data *drv = priv; 3705b9c547cSRui Paulo int ret = 0; 371*85732ac8SCy Schubert u32 channel; 3725b9c547cSRui Paulo 373*85732ac8SCy Schubert ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel); 374*85732ac8SCy Schubert if (ret != 0) 375*85732ac8SCy Schubert return ret; 3765b9c547cSRui Paulo 377*85732ac8SCy Schubert ret += nss_macsec_secy_tx_sa_next_pn_get(drv->secy_id, channel, sa->an, 378*85732ac8SCy Schubert &sa->next_pn); 379*85732ac8SCy Schubert 380*85732ac8SCy Schubert wpa_printf(MSG_DEBUG, "%s: npn=0x%x", __func__, sa->next_pn); 3815b9c547cSRui Paulo 3825b9c547cSRui Paulo return ret; 3835b9c547cSRui Paulo } 3845b9c547cSRui Paulo 3855b9c547cSRui Paulo 386*85732ac8SCy Schubert static int macsec_qca_set_transmit_next_pn(void *priv, struct transmit_sa *sa) 3875b9c547cSRui Paulo { 3885b9c547cSRui Paulo struct macsec_qca_data *drv = priv; 3895b9c547cSRui Paulo int ret = 0; 390*85732ac8SCy Schubert u32 channel; 3915b9c547cSRui Paulo 392*85732ac8SCy Schubert ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel); 393*85732ac8SCy Schubert if (ret != 0) 394*85732ac8SCy Schubert return ret; 3955b9c547cSRui Paulo 396*85732ac8SCy Schubert ret += nss_macsec_secy_tx_sa_next_pn_set(drv->secy_id, channel, sa->an, 397*85732ac8SCy Schubert sa->next_pn); 398*85732ac8SCy Schubert 399*85732ac8SCy Schubert wpa_printf(MSG_INFO, "%s: npn=0x%x", __func__, sa->next_pn); 4005b9c547cSRui Paulo 4015b9c547cSRui Paulo return ret; 4025b9c547cSRui Paulo } 4035b9c547cSRui Paulo 4045b9c547cSRui Paulo 4055b9c547cSRui Paulo static int macsec_qca_get_available_receive_sc(void *priv, u32 *channel) 4065b9c547cSRui Paulo { 4075b9c547cSRui Paulo struct macsec_qca_data *drv = priv; 4085b9c547cSRui Paulo int ret = 0; 4095b9c547cSRui Paulo u32 sc_ch = 0; 4105b9c547cSRui Paulo bool in_use = FALSE; 4115b9c547cSRui Paulo 4125b9c547cSRui Paulo for (sc_ch = 0; sc_ch < MAXSC; sc_ch++) { 4135b9c547cSRui Paulo ret = nss_macsec_secy_rx_sc_in_used_get(drv->secy_id, sc_ch, 4145b9c547cSRui Paulo &in_use); 4155b9c547cSRui Paulo if (ret) 4165b9c547cSRui Paulo continue; 4175b9c547cSRui Paulo 4185b9c547cSRui Paulo if (!in_use) { 4195b9c547cSRui Paulo *channel = sc_ch; 4205b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "%s: channel=%d", 4215b9c547cSRui Paulo __func__, *channel); 4225b9c547cSRui Paulo return 0; 4235b9c547cSRui Paulo } 4245b9c547cSRui Paulo } 4255b9c547cSRui Paulo 4265b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "%s: no available channel", __func__); 4275b9c547cSRui Paulo 4285b9c547cSRui Paulo return -1; 4295b9c547cSRui Paulo } 4305b9c547cSRui Paulo 4315b9c547cSRui Paulo 432*85732ac8SCy Schubert static int macsec_qca_create_receive_sc(void *priv, struct receive_sc *sc, 4335b9c547cSRui Paulo unsigned int conf_offset, 4345b9c547cSRui Paulo int validation) 4355b9c547cSRui Paulo { 4365b9c547cSRui Paulo struct macsec_qca_data *drv = priv; 4375b9c547cSRui Paulo int ret = 0; 4385b9c547cSRui Paulo fal_rx_prc_lut_t entry; 4395b9c547cSRui Paulo fal_rx_sc_validate_frame_e vf; 4405b9c547cSRui Paulo enum validate_frames validate_frames = validation; 441*85732ac8SCy Schubert u32 channel; 442*85732ac8SCy Schubert const u8 *sci_addr = sc->sci.addr; 443*85732ac8SCy Schubert u16 sci_port = be_to_host16(sc->sci.port); 444*85732ac8SCy Schubert 445*85732ac8SCy Schubert ret = macsec_qca_get_available_receive_sc(priv, &channel); 446*85732ac8SCy Schubert if (ret != 0) 447*85732ac8SCy Schubert return ret; 4485b9c547cSRui Paulo 4495b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel); 4505b9c547cSRui Paulo 4515b9c547cSRui Paulo /* rx prc lut */ 4525b9c547cSRui Paulo os_memset(&entry, 0, sizeof(entry)); 4535b9c547cSRui Paulo 4545b9c547cSRui Paulo os_memcpy(entry.sci, sci_addr, ETH_ALEN); 455*85732ac8SCy Schubert entry.sci[6] = (sci_port >> 8) & 0xff; 456*85732ac8SCy Schubert entry.sci[7] = sci_port & 0xff; 4575b9c547cSRui Paulo entry.sci_mask = 0xf; 4585b9c547cSRui Paulo 4595b9c547cSRui Paulo entry.valid = 1; 4605b9c547cSRui Paulo entry.channel = channel; 4615b9c547cSRui Paulo entry.action = FAL_RX_PRC_ACTION_PROCESS; 4625b9c547cSRui Paulo entry.offset = conf_offset; 4635b9c547cSRui Paulo 4645b9c547cSRui Paulo /* rx validate frame */ 4655b9c547cSRui Paulo if (validate_frames == Strict) 4665b9c547cSRui Paulo vf = FAL_RX_SC_VALIDATE_FRAME_STRICT; 4675b9c547cSRui Paulo else if (validate_frames == Checked) 4685b9c547cSRui Paulo vf = FAL_RX_SC_VALIDATE_FRAME_CHECK; 4695b9c547cSRui Paulo else 4705b9c547cSRui Paulo vf = FAL_RX_SC_VALIDATE_FRAME_DISABLED; 4715b9c547cSRui Paulo 4725b9c547cSRui Paulo ret += nss_macsec_secy_rx_prc_lut_set(drv->secy_id, channel, &entry); 4735b9c547cSRui Paulo ret += nss_macsec_secy_rx_sc_create(drv->secy_id, channel); 4745b9c547cSRui Paulo ret += nss_macsec_secy_rx_sc_validate_frame_set(drv->secy_id, channel, 4755b9c547cSRui Paulo vf); 4765b9c547cSRui Paulo ret += nss_macsec_secy_rx_sc_replay_protect_set(drv->secy_id, channel, 4775b9c547cSRui Paulo drv->replay_protect); 4785b9c547cSRui Paulo ret += nss_macsec_secy_rx_sc_anti_replay_window_set(drv->secy_id, 4795b9c547cSRui Paulo channel, 4805b9c547cSRui Paulo drv->replay_window); 4815b9c547cSRui Paulo 482*85732ac8SCy Schubert macsec_qca_register_receive_channel(drv, sc, channel); 483*85732ac8SCy Schubert 4845b9c547cSRui Paulo return ret; 4855b9c547cSRui Paulo } 4865b9c547cSRui Paulo 4875b9c547cSRui Paulo 488*85732ac8SCy Schubert static int macsec_qca_delete_receive_sc(void *priv, struct receive_sc *sc) 4895b9c547cSRui Paulo { 4905b9c547cSRui Paulo struct macsec_qca_data *drv = priv; 491*85732ac8SCy Schubert int ret; 4925b9c547cSRui Paulo fal_rx_prc_lut_t entry; 493*85732ac8SCy Schubert u32 channel; 494*85732ac8SCy Schubert 495*85732ac8SCy Schubert ret = macsec_qca_lookup_receive_channel(priv, sc, &channel); 496*85732ac8SCy Schubert if (ret != 0) 497*85732ac8SCy Schubert return ret; 4985b9c547cSRui Paulo 4995b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel); 5005b9c547cSRui Paulo 5015b9c547cSRui Paulo /* rx prc lut */ 5025b9c547cSRui Paulo os_memset(&entry, 0, sizeof(entry)); 5035b9c547cSRui Paulo 5045b9c547cSRui Paulo ret += nss_macsec_secy_rx_sc_del(drv->secy_id, channel); 5055b9c547cSRui Paulo ret += nss_macsec_secy_rx_prc_lut_set(drv->secy_id, channel, &entry); 5065b9c547cSRui Paulo 5075b9c547cSRui Paulo return ret; 5085b9c547cSRui Paulo } 5095b9c547cSRui Paulo 5105b9c547cSRui Paulo 511*85732ac8SCy Schubert static int macsec_qca_create_receive_sa(void *priv, struct receive_sa *sa) 5125b9c547cSRui Paulo { 5135b9c547cSRui Paulo struct macsec_qca_data *drv = priv; 514*85732ac8SCy Schubert int ret; 5155b9c547cSRui Paulo fal_rx_sak_t rx_sak; 5165b9c547cSRui Paulo int i = 0; 517*85732ac8SCy Schubert u32 channel; 518*85732ac8SCy Schubert fal_rx_prc_lut_t entry; 519*85732ac8SCy Schubert u32 offset; 520*85732ac8SCy Schubert 521*85732ac8SCy Schubert ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel); 522*85732ac8SCy Schubert if (ret != 0) 523*85732ac8SCy Schubert return ret; 5245b9c547cSRui Paulo 5255b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "%s, channel=%d, an=%d, lpn=0x%x", 526*85732ac8SCy Schubert __func__, channel, sa->an, sa->lowest_pn); 5275b9c547cSRui Paulo 5285b9c547cSRui Paulo os_memset(&rx_sak, 0, sizeof(rx_sak)); 529*85732ac8SCy Schubert rx_sak.sak_len = sa->pkey->key_len; 530*85732ac8SCy Schubert if (sa->pkey->key_len == SAK_128_LEN) { 5315b9c547cSRui Paulo for (i = 0; i < 16; i++) 532*85732ac8SCy Schubert rx_sak.sak[i] = sa->pkey->key[15 - i]; 533*85732ac8SCy Schubert } else if (sa->pkey->key_len == SAK_256_LEN) { 534*85732ac8SCy Schubert for (i = 0; i < 16; i++) { 535*85732ac8SCy Schubert rx_sak.sak1[i] = sa->pkey->key[15 - i]; 536*85732ac8SCy Schubert rx_sak.sak[i] = sa->pkey->key[31 - i]; 537*85732ac8SCy Schubert } 538*85732ac8SCy Schubert } else { 539*85732ac8SCy Schubert return -1; 540*85732ac8SCy Schubert } 5415b9c547cSRui Paulo 542*85732ac8SCy Schubert if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_0) 543*85732ac8SCy Schubert offset = 0; 544*85732ac8SCy Schubert else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_30) 545*85732ac8SCy Schubert offset = 30; 546*85732ac8SCy Schubert else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_50) 547*85732ac8SCy Schubert offset = 50; 548*85732ac8SCy Schubert else 549*85732ac8SCy Schubert return -1; 550*85732ac8SCy Schubert ret += nss_macsec_secy_rx_prc_lut_get(drv->secy_id, channel, &entry); 551*85732ac8SCy Schubert entry.offset = offset; 552*85732ac8SCy Schubert ret += nss_macsec_secy_rx_prc_lut_set(drv->secy_id, channel, &entry); 553*85732ac8SCy Schubert ret += nss_macsec_secy_rx_sa_create(drv->secy_id, channel, sa->an); 554*85732ac8SCy Schubert ret += nss_macsec_secy_rx_sak_set(drv->secy_id, channel, sa->an, 555*85732ac8SCy Schubert &rx_sak); 5565b9c547cSRui Paulo 5575b9c547cSRui Paulo return ret; 5585b9c547cSRui Paulo } 5595b9c547cSRui Paulo 5605b9c547cSRui Paulo 561*85732ac8SCy Schubert static int macsec_qca_enable_receive_sa(void *priv, struct receive_sa *sa) 5625b9c547cSRui Paulo { 5635b9c547cSRui Paulo struct macsec_qca_data *drv = priv; 564*85732ac8SCy Schubert int ret; 565*85732ac8SCy Schubert u32 channel; 5665b9c547cSRui Paulo 567*85732ac8SCy Schubert ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel); 568*85732ac8SCy Schubert if (ret != 0) 569*85732ac8SCy Schubert return ret; 5705b9c547cSRui Paulo 571*85732ac8SCy Schubert wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel, 572*85732ac8SCy Schubert sa->an); 573*85732ac8SCy Schubert 574*85732ac8SCy Schubert ret += nss_macsec_secy_rx_sa_en_set(drv->secy_id, channel, sa->an, 575*85732ac8SCy Schubert TRUE); 5765b9c547cSRui Paulo 5775b9c547cSRui Paulo return ret; 5785b9c547cSRui Paulo } 5795b9c547cSRui Paulo 5805b9c547cSRui Paulo 581*85732ac8SCy Schubert static int macsec_qca_disable_receive_sa(void *priv, struct receive_sa *sa) 5825b9c547cSRui Paulo { 5835b9c547cSRui Paulo struct macsec_qca_data *drv = priv; 584*85732ac8SCy Schubert int ret; 585*85732ac8SCy Schubert u32 channel; 5865b9c547cSRui Paulo 587*85732ac8SCy Schubert ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel); 588*85732ac8SCy Schubert if (ret != 0) 589*85732ac8SCy Schubert return ret; 5905b9c547cSRui Paulo 591*85732ac8SCy Schubert wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel, 592*85732ac8SCy Schubert sa->an); 593*85732ac8SCy Schubert 594*85732ac8SCy Schubert ret += nss_macsec_secy_rx_sa_en_set(drv->secy_id, channel, sa->an, 595*85732ac8SCy Schubert FALSE); 5965b9c547cSRui Paulo 5975b9c547cSRui Paulo return ret; 5985b9c547cSRui Paulo } 5995b9c547cSRui Paulo 6005b9c547cSRui Paulo 6015b9c547cSRui Paulo static int macsec_qca_get_available_transmit_sc(void *priv, u32 *channel) 6025b9c547cSRui Paulo { 6035b9c547cSRui Paulo struct macsec_qca_data *drv = priv; 6045b9c547cSRui Paulo u32 sc_ch = 0; 6055b9c547cSRui Paulo bool in_use = FALSE; 6065b9c547cSRui Paulo 6075b9c547cSRui Paulo for (sc_ch = 0; sc_ch < MAXSC; sc_ch++) { 608*85732ac8SCy Schubert if (nss_macsec_secy_tx_sc_in_used_get(drv->secy_id, sc_ch, 609*85732ac8SCy Schubert &in_use)) 6105b9c547cSRui Paulo continue; 6115b9c547cSRui Paulo 6125b9c547cSRui Paulo if (!in_use) { 6135b9c547cSRui Paulo *channel = sc_ch; 6145b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "%s: channel=%d", 6155b9c547cSRui Paulo __func__, *channel); 6165b9c547cSRui Paulo return 0; 6175b9c547cSRui Paulo } 6185b9c547cSRui Paulo } 6195b9c547cSRui Paulo 6205b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "%s: no avaiable channel", __func__); 6215b9c547cSRui Paulo 6225b9c547cSRui Paulo return -1; 6235b9c547cSRui Paulo } 6245b9c547cSRui Paulo 6255b9c547cSRui Paulo 626*85732ac8SCy Schubert static int macsec_qca_create_transmit_sc(void *priv, struct transmit_sc *sc, 6275b9c547cSRui Paulo unsigned int conf_offset) 6285b9c547cSRui Paulo { 6295b9c547cSRui Paulo struct macsec_qca_data *drv = priv; 630*85732ac8SCy Schubert int ret; 6315b9c547cSRui Paulo fal_tx_class_lut_t entry; 6325b9c547cSRui Paulo u8 psci[ETH_ALEN + 2]; 633*85732ac8SCy Schubert u32 channel; 634*85732ac8SCy Schubert u16 sci_port = be_to_host16(sc->sci.port); 635*85732ac8SCy Schubert 636*85732ac8SCy Schubert ret = macsec_qca_get_available_transmit_sc(priv, &channel); 637*85732ac8SCy Schubert if (ret != 0) 638*85732ac8SCy Schubert return ret; 6395b9c547cSRui Paulo 6405b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel); 6415b9c547cSRui Paulo 6425b9c547cSRui Paulo /* class lut */ 6435b9c547cSRui Paulo os_memset(&entry, 0, sizeof(entry)); 6445b9c547cSRui Paulo 6455b9c547cSRui Paulo entry.valid = 1; 6465b9c547cSRui Paulo entry.action = FAL_TX_CLASS_ACTION_FORWARD; 6475b9c547cSRui Paulo entry.channel = channel; 6485b9c547cSRui Paulo 649*85732ac8SCy Schubert os_memcpy(psci, sc->sci.addr, ETH_ALEN); 650*85732ac8SCy Schubert psci[6] = (sci_port >> 8) & 0xff; 651*85732ac8SCy Schubert psci[7] = sci_port & 0xff; 6525b9c547cSRui Paulo 6535b9c547cSRui Paulo ret += nss_macsec_secy_tx_class_lut_set(drv->secy_id, channel, &entry); 6545b9c547cSRui Paulo ret += nss_macsec_secy_tx_sc_create(drv->secy_id, channel, psci, 8); 6555b9c547cSRui Paulo ret += nss_macsec_secy_tx_sc_protect_set(drv->secy_id, channel, 6565b9c547cSRui Paulo drv->protect_frames); 6575b9c547cSRui Paulo ret += nss_macsec_secy_tx_sc_confidentiality_offset_set(drv->secy_id, 6585b9c547cSRui Paulo channel, 6595b9c547cSRui Paulo conf_offset); 6605b9c547cSRui Paulo 661*85732ac8SCy Schubert macsec_qca_register_transmit_channel(drv, sc, channel); 662*85732ac8SCy Schubert 6635b9c547cSRui Paulo return ret; 6645b9c547cSRui Paulo } 6655b9c547cSRui Paulo 6665b9c547cSRui Paulo 667*85732ac8SCy Schubert static int macsec_qca_delete_transmit_sc(void *priv, struct transmit_sc *sc) 6685b9c547cSRui Paulo { 6695b9c547cSRui Paulo struct macsec_qca_data *drv = priv; 670*85732ac8SCy Schubert int ret; 6715b9c547cSRui Paulo fal_tx_class_lut_t entry; 672*85732ac8SCy Schubert u32 channel; 673*85732ac8SCy Schubert 674*85732ac8SCy Schubert ret = macsec_qca_lookup_transmit_channel(priv, sc, &channel); 675*85732ac8SCy Schubert if (ret != 0) 676*85732ac8SCy Schubert return ret; 6775b9c547cSRui Paulo 6785b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel); 6795b9c547cSRui Paulo 6805b9c547cSRui Paulo /* class lut */ 6815b9c547cSRui Paulo os_memset(&entry, 0, sizeof(entry)); 6825b9c547cSRui Paulo 6835b9c547cSRui Paulo ret += nss_macsec_secy_tx_class_lut_set(drv->secy_id, channel, &entry); 6845b9c547cSRui Paulo ret += nss_macsec_secy_tx_sc_del(drv->secy_id, channel); 6855b9c547cSRui Paulo 6865b9c547cSRui Paulo return ret; 6875b9c547cSRui Paulo } 6885b9c547cSRui Paulo 6895b9c547cSRui Paulo 690*85732ac8SCy Schubert static int macsec_qca_create_transmit_sa(void *priv, struct transmit_sa *sa) 6915b9c547cSRui Paulo { 6925b9c547cSRui Paulo struct macsec_qca_data *drv = priv; 693*85732ac8SCy Schubert int ret; 6945b9c547cSRui Paulo u8 tci = 0; 6955b9c547cSRui Paulo fal_tx_sak_t tx_sak; 6965b9c547cSRui Paulo int i; 697*85732ac8SCy Schubert u32 channel; 698*85732ac8SCy Schubert u32 offset; 699*85732ac8SCy Schubert 700*85732ac8SCy Schubert ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel); 701*85732ac8SCy Schubert if (ret != 0) 702*85732ac8SCy Schubert return ret; 7035b9c547cSRui Paulo 7045b9c547cSRui Paulo wpa_printf(MSG_DEBUG, 7055b9c547cSRui Paulo "%s: channel=%d, an=%d, next_pn=0x%x, confidentiality=%d", 706*85732ac8SCy Schubert __func__, channel, sa->an, sa->next_pn, sa->confidentiality); 7075b9c547cSRui Paulo 7085b9c547cSRui Paulo if (drv->always_include_sci) 7095b9c547cSRui Paulo tci |= TCI_SC; 7105b9c547cSRui Paulo else if (drv->use_es) 7115b9c547cSRui Paulo tci |= TCI_ES; 7125b9c547cSRui Paulo else if (drv->use_scb) 7135b9c547cSRui Paulo tci |= TCI_SCB; 7145b9c547cSRui Paulo 715*85732ac8SCy Schubert if (sa->confidentiality) 7165b9c547cSRui Paulo tci |= TCI_E | TCI_C; 7175b9c547cSRui Paulo 7185b9c547cSRui Paulo os_memset(&tx_sak, 0, sizeof(tx_sak)); 719*85732ac8SCy Schubert tx_sak.sak_len = sa->pkey->key_len; 720*85732ac8SCy Schubert if (sa->pkey->key_len == SAK_128_LEN) { 7215b9c547cSRui Paulo for (i = 0; i < 16; i++) 722*85732ac8SCy Schubert tx_sak.sak[i] = sa->pkey->key[15 - i]; 723*85732ac8SCy Schubert } else if (sa->pkey->key_len == SAK_256_LEN) { 724*85732ac8SCy Schubert for (i = 0; i < 16; i++) { 725*85732ac8SCy Schubert tx_sak.sak1[i] = sa->pkey->key[15 - i]; 726*85732ac8SCy Schubert tx_sak.sak[i] = sa->pkey->key[31 - i]; 727*85732ac8SCy Schubert } 728*85732ac8SCy Schubert } else { 729*85732ac8SCy Schubert return -1; 730*85732ac8SCy Schubert } 7315b9c547cSRui Paulo 732*85732ac8SCy Schubert if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_0) 733*85732ac8SCy Schubert offset = 0; 734*85732ac8SCy Schubert else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_30) 735*85732ac8SCy Schubert offset = 30; 736*85732ac8SCy Schubert else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_50) 737*85732ac8SCy Schubert offset = 50; 738*85732ac8SCy Schubert else 739*85732ac8SCy Schubert return -1; 740*85732ac8SCy Schubert ret += nss_macsec_secy_tx_sc_confidentiality_offset_set(drv->secy_id, 741*85732ac8SCy Schubert channel, 742*85732ac8SCy Schubert offset); 743*85732ac8SCy Schubert ret += nss_macsec_secy_tx_sa_next_pn_set(drv->secy_id, channel, sa->an, 744*85732ac8SCy Schubert sa->next_pn); 745*85732ac8SCy Schubert ret += nss_macsec_secy_tx_sak_set(drv->secy_id, channel, sa->an, 746*85732ac8SCy Schubert &tx_sak); 7475b9c547cSRui Paulo ret += nss_macsec_secy_tx_sc_tci_7_2_set(drv->secy_id, channel, 7485b9c547cSRui Paulo (tci >> 2)); 749*85732ac8SCy Schubert ret += nss_macsec_secy_tx_sc_an_set(drv->secy_id, channel, sa->an); 7505b9c547cSRui Paulo 7515b9c547cSRui Paulo return ret; 7525b9c547cSRui Paulo } 7535b9c547cSRui Paulo 7545b9c547cSRui Paulo 755*85732ac8SCy Schubert static int macsec_qca_enable_transmit_sa(void *priv, struct transmit_sa *sa) 7565b9c547cSRui Paulo { 7575b9c547cSRui Paulo struct macsec_qca_data *drv = priv; 758*85732ac8SCy Schubert int ret; 759*85732ac8SCy Schubert u32 channel; 7605b9c547cSRui Paulo 761*85732ac8SCy Schubert ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel); 762*85732ac8SCy Schubert if (ret != 0) 763*85732ac8SCy Schubert return ret; 7645b9c547cSRui Paulo 765*85732ac8SCy Schubert wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel, 766*85732ac8SCy Schubert sa->an); 767*85732ac8SCy Schubert 768*85732ac8SCy Schubert ret += nss_macsec_secy_tx_sa_en_set(drv->secy_id, channel, sa->an, 769*85732ac8SCy Schubert TRUE); 7705b9c547cSRui Paulo 7715b9c547cSRui Paulo return ret; 7725b9c547cSRui Paulo } 7735b9c547cSRui Paulo 7745b9c547cSRui Paulo 775*85732ac8SCy Schubert static int macsec_qca_disable_transmit_sa(void *priv, struct transmit_sa *sa) 7765b9c547cSRui Paulo { 7775b9c547cSRui Paulo struct macsec_qca_data *drv = priv; 778*85732ac8SCy Schubert int ret; 779*85732ac8SCy Schubert u32 channel; 7805b9c547cSRui Paulo 781*85732ac8SCy Schubert ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel); 782*85732ac8SCy Schubert if (ret != 0) 783*85732ac8SCy Schubert return ret; 7845b9c547cSRui Paulo 785*85732ac8SCy Schubert wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel, 786*85732ac8SCy Schubert sa->an); 787*85732ac8SCy Schubert 788*85732ac8SCy Schubert ret += nss_macsec_secy_tx_sa_en_set(drv->secy_id, channel, sa->an, 789*85732ac8SCy Schubert FALSE); 7905b9c547cSRui Paulo 7915b9c547cSRui Paulo return ret; 7925b9c547cSRui Paulo } 7935b9c547cSRui Paulo 7945b9c547cSRui Paulo 7955b9c547cSRui Paulo const struct wpa_driver_ops wpa_driver_macsec_qca_ops = { 7965b9c547cSRui Paulo .name = "macsec_qca", 7975b9c547cSRui Paulo .desc = "QCA MACsec Ethernet driver", 798*85732ac8SCy Schubert .get_ssid = driver_wired_get_ssid, 799*85732ac8SCy Schubert .get_bssid = driver_wired_get_bssid, 800*85732ac8SCy Schubert .get_capa = driver_wired_get_capa, 8015b9c547cSRui Paulo .init = macsec_qca_init, 8025b9c547cSRui Paulo .deinit = macsec_qca_deinit, 8035b9c547cSRui Paulo 8045b9c547cSRui Paulo .macsec_init = macsec_qca_macsec_init, 8055b9c547cSRui Paulo .macsec_deinit = macsec_qca_macsec_deinit, 806*85732ac8SCy Schubert .macsec_get_capability = macsec_qca_get_capability, 8075b9c547cSRui Paulo .enable_protect_frames = macsec_qca_enable_protect_frames, 8085b9c547cSRui Paulo .set_replay_protect = macsec_qca_set_replay_protect, 8095b9c547cSRui Paulo .set_current_cipher_suite = macsec_qca_set_current_cipher_suite, 8105b9c547cSRui Paulo .enable_controlled_port = macsec_qca_enable_controlled_port, 8115b9c547cSRui Paulo .get_receive_lowest_pn = macsec_qca_get_receive_lowest_pn, 8125b9c547cSRui Paulo .get_transmit_next_pn = macsec_qca_get_transmit_next_pn, 8135b9c547cSRui Paulo .set_transmit_next_pn = macsec_qca_set_transmit_next_pn, 8145b9c547cSRui Paulo .create_receive_sc = macsec_qca_create_receive_sc, 8155b9c547cSRui Paulo .delete_receive_sc = macsec_qca_delete_receive_sc, 8165b9c547cSRui Paulo .create_receive_sa = macsec_qca_create_receive_sa, 8175b9c547cSRui Paulo .enable_receive_sa = macsec_qca_enable_receive_sa, 8185b9c547cSRui Paulo .disable_receive_sa = macsec_qca_disable_receive_sa, 8195b9c547cSRui Paulo .create_transmit_sc = macsec_qca_create_transmit_sc, 8205b9c547cSRui Paulo .delete_transmit_sc = macsec_qca_delete_transmit_sc, 8215b9c547cSRui Paulo .create_transmit_sa = macsec_qca_create_transmit_sa, 8225b9c547cSRui Paulo .enable_transmit_sa = macsec_qca_enable_transmit_sa, 8235b9c547cSRui Paulo .disable_transmit_sa = macsec_qca_disable_transmit_sa, 8245b9c547cSRui Paulo }; 825