2 * Wired Ethernet driver interface for QCA MACsec driver
3 * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>
4 * Copyright (c) 2004, Gunter Burchardt <tira@isx.de>
5 * Copyright (c) 2013-2014, Qualcomm Atheros, Inc.
7 * This software may be distributed under the terms of the BSD license.
8 * See README for more details.
12 #include <sys/ioctl.h>
16 #include <netpacket/packet.h>
17 #include <net/if_arp.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__) */
25 #include <sys/sockio.h>
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"
35 #include "nss_macsec_secy.h"
36 #include "nss_macsec_secy_rx.h"
37 #include "nss_macsec_secy_tx.h"
41 /* TCI field definition */
56 static const u8 pae_group_addr
[ETH_ALEN
] =
57 { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 };
59 struct macsec_qca_data
{
60 char ifname
[IFNAMSIZ
+ 1];
64 int sock
; /* raw packet socket for driver access */
66 int membership
, multi
, iff_allmulti
, iff_up
;
69 Boolean always_include_sci
;
72 Boolean protect_frames
;
73 Boolean replay_protect
;
78 static int macsec_qca_multicast_membership(int sock
, int ifindex
,
79 const u8
*addr
, int add
)
82 struct packet_mreq mreq
;
87 os_memset(&mreq
, 0, sizeof(mreq
));
88 mreq
.mr_ifindex
= ifindex
;
89 mreq
.mr_type
= PACKET_MR_MULTICAST
;
90 mreq
.mr_alen
= ETH_ALEN
;
91 os_memcpy(mreq
.mr_address
, addr
, ETH_ALEN
);
93 if (setsockopt(sock
, SOL_PACKET
,
94 add
? PACKET_ADD_MEMBERSHIP
: PACKET_DROP_MEMBERSHIP
,
95 &mreq
, sizeof(mreq
)) < 0) {
96 wpa_printf(MSG_ERROR
, "setsockopt: %s", strerror(errno
));
100 #else /* __linux__ */
102 #endif /* __linux__ */
106 static int macsec_qca_get_ssid(void *priv
, u8
*ssid
)
113 static int macsec_qca_get_bssid(void *priv
, u8
*bssid
)
115 /* Report PAE group address as the "BSSID" for macsec connection. */
116 os_memcpy(bssid
, pae_group_addr
, ETH_ALEN
);
121 static int macsec_qca_get_capa(void *priv
, struct wpa_driver_capa
*capa
)
123 os_memset(capa
, 0, sizeof(*capa
));
124 capa
->flags
= WPA_DRIVER_FLAGS_WIRED
;
129 static int macsec_qca_get_ifflags(const char *ifname
, int *flags
)
134 s
= socket(PF_INET
, SOCK_DGRAM
, 0);
136 wpa_printf(MSG_ERROR
, "socket: %s", strerror(errno
));
140 os_memset(&ifr
, 0, sizeof(ifr
));
141 os_strlcpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
142 if (ioctl(s
, SIOCGIFFLAGS
, (caddr_t
) &ifr
) < 0) {
143 wpa_printf(MSG_ERROR
, "ioctl[SIOCGIFFLAGS]: %s",
149 *flags
= ifr
.ifr_flags
& 0xffff;
154 static int macsec_qca_set_ifflags(const char *ifname
, int flags
)
159 s
= socket(PF_INET
, SOCK_DGRAM
, 0);
161 wpa_printf(MSG_ERROR
, "socket: %s", strerror(errno
));
165 os_memset(&ifr
, 0, sizeof(ifr
));
166 os_strlcpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
167 ifr
.ifr_flags
= flags
& 0xffff;
168 if (ioctl(s
, SIOCSIFFLAGS
, (caddr_t
) &ifr
) < 0) {
169 wpa_printf(MSG_ERROR
, "ioctl[SIOCSIFFLAGS]: %s",
179 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
180 static int macsec_qca_get_ifstatus(const char *ifname
, int *status
)
182 struct ifmediareq ifmr
;
185 s
= socket(PF_INET
, SOCK_DGRAM
, 0);
187 wpa_print(MSG_ERROR
, "socket: %s", strerror(errno
));
191 os_memset(&ifmr
, 0, sizeof(ifmr
));
192 os_strlcpy(ifmr
.ifm_name
, ifname
, IFNAMSIZ
);
193 if (ioctl(s
, SIOCGIFMEDIA
, (caddr_t
) &ifmr
) < 0) {
194 wpa_printf(MSG_ERROR
, "ioctl[SIOCGIFMEDIA]: %s",
200 *status
= (ifmr
.ifm_status
& (IFM_ACTIVE
| IFM_AVALID
)) ==
201 (IFM_ACTIVE
| IFM_AVALID
);
205 #endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(FreeBSD_kernel__) */
208 static int macsec_qca_multi(const char *ifname
, const u8
*addr
, int add
)
217 s
= socket(PF_INET
, SOCK_DGRAM
, 0);
219 wpa_printf(MSG_ERROR
, "socket: %s", strerror(errno
));
223 os_memset(&ifr
, 0, sizeof(ifr
));
224 os_strlcpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
226 ifr
.ifr_hwaddr
.sa_family
= AF_UNSPEC
;
227 os_memcpy(ifr
.ifr_hwaddr
.sa_data
, addr
, ETH_ALEN
);
228 #endif /* __linux__ */
229 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
231 struct sockaddr_dl
*dlp
;
232 dlp
= (struct sockaddr_dl
*) &ifr
.ifr_addr
;
233 dlp
->sdl_len
= sizeof(struct sockaddr_dl
);
234 dlp
->sdl_family
= AF_LINK
;
237 dlp
->sdl_alen
= ETH_ALEN
;
239 os_memcpy(LLADDR(dlp
), addr
, ETH_ALEN
);
241 #endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(FreeBSD_kernel__) */
242 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
244 struct sockaddr
*sap
;
245 sap
= (struct sockaddr
*) &ifr
.ifr_addr
;
246 sap
->sa_len
= sizeof(struct sockaddr
);
247 sap
->sa_family
= AF_UNSPEC
;
248 os_memcpy(sap
->sa_data
, addr
, ETH_ALEN
);
250 #endif /* defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__) */
252 if (ioctl(s
, add
? SIOCADDMULTI
: SIOCDELMULTI
, (caddr_t
) &ifr
) < 0) {
253 wpa_printf(MSG_ERROR
, "ioctl[SIOC{ADD/DEL}MULTI]: %s",
263 static void __macsec_drv_init(struct macsec_qca_data
*drv
)
266 fal_rx_ctl_filt_t rx_ctl_filt
;
267 fal_tx_ctl_filt_t tx_ctl_filt
;
269 wpa_printf(MSG_INFO
, "%s: secy_id=%d", __func__
, drv
->secy_id
);
271 /* Enable Secy and Let EAPoL bypass */
272 ret
= nss_macsec_secy_en_set(drv
->secy_id
, TRUE
);
274 wpa_printf(MSG_ERROR
, "nss_macsec_secy_en_set: FAIL");
276 ret
= nss_macsec_secy_sc_sa_mapping_mode_set(drv
->secy_id
,
279 wpa_printf(MSG_ERROR
,
280 "nss_macsec_secy_sc_sa_mapping_mode_set: FAIL");
282 os_memset(&rx_ctl_filt
, 0, sizeof(rx_ctl_filt
));
283 rx_ctl_filt
.bypass
= 1;
284 rx_ctl_filt
.match_type
= IG_CTL_COMPARE_ETHER_TYPE
;
285 rx_ctl_filt
.match_mask
= 0xffff;
286 rx_ctl_filt
.ether_type_da_range
= 0x888e;
287 ret
= nss_macsec_secy_rx_ctl_filt_set(drv
->secy_id
, 0, &rx_ctl_filt
);
289 wpa_printf(MSG_ERROR
, "nss_macsec_secy_rx_ctl_filt_set: FAIL");
291 os_memset(&tx_ctl_filt
, 0, sizeof(tx_ctl_filt
));
292 tx_ctl_filt
.bypass
= 1;
293 tx_ctl_filt
.match_type
= EG_CTL_COMPARE_ETHER_TYPE
;
294 tx_ctl_filt
.match_mask
= 0xffff;
295 tx_ctl_filt
.ether_type_da_range
= 0x888e;
296 ret
= nss_macsec_secy_tx_ctl_filt_set(drv
->secy_id
, 0, &tx_ctl_filt
);
298 wpa_printf(MSG_ERROR
, "nss_macsec_secy_tx_ctl_filt_set: FAIL");
302 static void __macsec_drv_deinit(struct macsec_qca_data
*drv
)
304 nss_macsec_secy_en_set(drv
->secy_id
, FALSE
);
305 nss_macsec_secy_rx_sc_del_all(drv
->secy_id
);
306 nss_macsec_secy_tx_sc_del_all(drv
->secy_id
);
310 static void * macsec_qca_init(void *ctx
, const char *ifname
)
312 struct macsec_qca_data
*drv
;
315 drv
= os_zalloc(sizeof(*drv
));
318 os_strlcpy(drv
->ifname
, ifname
, sizeof(drv
->ifname
));
321 /* Board specific settings */
322 if (os_memcmp("eth2", drv
->ifname
, 4) == 0)
324 else if (os_memcmp("eth3", drv
->ifname
, 4) == 0)
330 drv
->pf_sock
= socket(PF_PACKET
, SOCK_DGRAM
, 0);
331 if (drv
->pf_sock
< 0)
332 wpa_printf(MSG_ERROR
, "socket(PF_PACKET): %s", strerror(errno
));
333 #else /* __linux__ */
335 #endif /* __linux__ */
337 if (macsec_qca_get_ifflags(ifname
, &flags
) == 0 &&
339 macsec_qca_set_ifflags(ifname
, flags
| IFF_UP
) == 0) {
343 if (macsec_qca_multicast_membership(drv
->pf_sock
,
344 if_nametoindex(drv
->ifname
),
345 pae_group_addr
, 1) == 0) {
346 wpa_printf(MSG_DEBUG
,
347 "%s: Added multicast membership with packet socket",
350 } else if (macsec_qca_multi(ifname
, pae_group_addr
, 1) == 0) {
351 wpa_printf(MSG_DEBUG
,
352 "%s: Added multicast membership with SIOCADDMULTI",
355 } else if (macsec_qca_get_ifflags(ifname
, &flags
) < 0) {
356 wpa_printf(MSG_INFO
, "%s: Could not get interface flags",
360 } else if (flags
& IFF_ALLMULTI
) {
361 wpa_printf(MSG_DEBUG
,
362 "%s: Interface is already configured for multicast",
364 } else if (macsec_qca_set_ifflags(ifname
, flags
| IFF_ALLMULTI
) < 0) {
365 wpa_printf(MSG_INFO
, "%s: Failed to enable allmulti",
370 wpa_printf(MSG_DEBUG
, "%s: Enabled allmulti mode", __func__
);
371 drv
->iff_allmulti
= 1;
373 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
376 wpa_printf(MSG_DEBUG
, "%s: waiting for link to become active",
378 while (macsec_qca_get_ifstatus(ifname
, &status
) == 0 &&
382 #endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(FreeBSD_kernel__) */
388 static void macsec_qca_deinit(void *priv
)
390 struct macsec_qca_data
*drv
= priv
;
393 if (drv
->membership
&&
394 macsec_qca_multicast_membership(drv
->pf_sock
,
395 if_nametoindex(drv
->ifname
),
396 pae_group_addr
, 0) < 0) {
397 wpa_printf(MSG_DEBUG
,
398 "%s: Failed to remove PAE multicast group (PACKET)",
403 macsec_qca_multi(drv
->ifname
, pae_group_addr
, 0) < 0) {
404 wpa_printf(MSG_DEBUG
,
405 "%s: Failed to remove PAE multicast group (SIOCDELMULTI)",
409 if (drv
->iff_allmulti
&&
410 (macsec_qca_get_ifflags(drv
->ifname
, &flags
) < 0 ||
411 macsec_qca_set_ifflags(drv
->ifname
, flags
& ~IFF_ALLMULTI
) < 0)) {
412 wpa_printf(MSG_DEBUG
, "%s: Failed to disable allmulti mode",
417 macsec_qca_get_ifflags(drv
->ifname
, &flags
) == 0 &&
419 macsec_qca_set_ifflags(drv
->ifname
, flags
& ~IFF_UP
) < 0) {
420 wpa_printf(MSG_DEBUG
, "%s: Failed to set the interface down",
424 if (drv
->pf_sock
!= -1)
431 static int macsec_qca_macsec_init(void *priv
, struct macsec_init_params
*params
)
433 struct macsec_qca_data
*drv
= priv
;
435 drv
->always_include_sci
= params
->always_include_sci
;
436 drv
->use_es
= params
->use_es
;
437 drv
->use_scb
= params
->use_scb
;
439 wpa_printf(MSG_DEBUG
, "%s: es=%d, scb=%d, sci=%d",
440 __func__
, drv
->use_es
, drv
->use_scb
,
441 drv
->always_include_sci
);
443 __macsec_drv_init(drv
);
449 static int macsec_qca_macsec_deinit(void *priv
)
451 struct macsec_qca_data
*drv
= priv
;
453 wpa_printf(MSG_DEBUG
, "%s", __func__
);
455 __macsec_drv_deinit(drv
);
461 static int macsec_qca_enable_protect_frames(void *priv
, Boolean enabled
)
463 struct macsec_qca_data
*drv
= priv
;
466 wpa_printf(MSG_DEBUG
, "%s: enabled=%d", __func__
, enabled
);
468 drv
->protect_frames
= enabled
;
474 static int macsec_qca_set_replay_protect(void *priv
, Boolean enabled
,
477 struct macsec_qca_data
*drv
= priv
;
480 wpa_printf(MSG_DEBUG
, "%s: enabled=%d, win=%u",
481 __func__
, enabled
, window
);
483 drv
->replay_protect
= enabled
;
484 drv
->replay_window
= window
;
490 static int macsec_qca_set_current_cipher_suite(void *priv
, u64 cs
)
492 if (cs
!= CS_ID_GCM_AES_128
) {
493 wpa_printf(MSG_ERROR
,
494 "%s: NOT supported CipherSuite: %016" PRIx64
,
499 /* Support default Cipher Suite 0080020001000001 (GCM-AES-128) */
500 wpa_printf(MSG_DEBUG
, "%s: default support aes-gcm-128", __func__
);
506 static int macsec_qca_enable_controlled_port(void *priv
, Boolean enabled
)
508 struct macsec_qca_data
*drv
= priv
;
511 wpa_printf(MSG_DEBUG
, "%s: enable=%d", __func__
, enabled
);
513 ret
+= nss_macsec_secy_controlled_port_en_set(drv
->secy_id
, enabled
);
519 static int macsec_qca_get_receive_lowest_pn(void *priv
, struct receive_sa
*sa
)
521 struct macsec_qca_data
*drv
= priv
;
524 bool enabled
= FALSE
;
526 u32 channel
= sa
->sc
->channel
;
528 ret
+= nss_macsec_secy_rx_sa_next_pn_get(drv
->secy_id
, channel
, sa
->an
,
530 ret
+= nss_macsec_secy_rx_sc_replay_protect_get(drv
->secy_id
, channel
,
532 ret
+= nss_macsec_secy_rx_sc_anti_replay_window_get(drv
->secy_id
,
536 sa
->lowest_pn
= (next_pn
> win
) ? (next_pn
- win
) : 1;
538 sa
->lowest_pn
= next_pn
;
540 wpa_printf(MSG_DEBUG
, "%s: lpn=0x%x", __func__
, sa
->lowest_pn
);
546 static int macsec_qca_get_transmit_next_pn(void *priv
, struct transmit_sa
*sa
)
548 struct macsec_qca_data
*drv
= priv
;
550 u32 channel
= sa
->sc
->channel
;
552 ret
+= nss_macsec_secy_tx_sa_next_pn_get(drv
->secy_id
, channel
, sa
->an
,
555 wpa_printf(MSG_DEBUG
, "%s: npn=0x%x", __func__
, sa
->next_pn
);
561 int macsec_qca_set_transmit_next_pn(void *priv
, struct transmit_sa
*sa
)
563 struct macsec_qca_data
*drv
= priv
;
565 u32 channel
= sa
->sc
->channel
;
568 ret
+= nss_macsec_secy_tx_sa_next_pn_set(drv
->secy_id
, channel
, sa
->an
,
571 wpa_printf(MSG_INFO
, "%s: npn=0x%x", __func__
, sa
->next_pn
);
577 static int macsec_qca_get_available_receive_sc(void *priv
, u32
*channel
)
579 struct macsec_qca_data
*drv
= priv
;
584 for (sc_ch
= 0; sc_ch
< MAXSC
; sc_ch
++) {
585 ret
= nss_macsec_secy_rx_sc_in_used_get(drv
->secy_id
, sc_ch
,
592 wpa_printf(MSG_DEBUG
, "%s: channel=%d",
598 wpa_printf(MSG_DEBUG
, "%s: no available channel", __func__
);
604 static int macsec_qca_create_receive_sc(void *priv
, struct receive_sc
*sc
,
605 unsigned int conf_offset
,
608 struct macsec_qca_data
*drv
= priv
;
610 fal_rx_prc_lut_t entry
;
611 fal_rx_sc_validate_frame_e vf
;
612 enum validate_frames validate_frames
= validation
;
613 u32 channel
= sc
->channel
;
614 const u8
*sci_addr
= sc
->sci
.addr
;
615 u16 sci_port
= be_to_host16(sc
->sci
.port
);
617 wpa_printf(MSG_DEBUG
, "%s: channel=%d", __func__
, channel
);
620 os_memset(&entry
, 0, sizeof(entry
));
622 os_memcpy(entry
.sci
, sci_addr
, ETH_ALEN
);
623 entry
.sci
[6] = (sci_port
>> 8) & 0xf;
624 entry
.sci
[7] = sci_port
& 0xf;
625 entry
.sci_mask
= 0xf;
628 entry
.channel
= channel
;
629 entry
.action
= FAL_RX_PRC_ACTION_PROCESS
;
630 entry
.offset
= conf_offset
;
632 /* rx validate frame */
633 if (validate_frames
== Strict
)
634 vf
= FAL_RX_SC_VALIDATE_FRAME_STRICT
;
635 else if (validate_frames
== Checked
)
636 vf
= FAL_RX_SC_VALIDATE_FRAME_CHECK
;
638 vf
= FAL_RX_SC_VALIDATE_FRAME_DISABLED
;
640 ret
+= nss_macsec_secy_rx_prc_lut_set(drv
->secy_id
, channel
, &entry
);
641 ret
+= nss_macsec_secy_rx_sc_create(drv
->secy_id
, channel
);
642 ret
+= nss_macsec_secy_rx_sc_validate_frame_set(drv
->secy_id
, channel
,
644 ret
+= nss_macsec_secy_rx_sc_replay_protect_set(drv
->secy_id
, channel
,
645 drv
->replay_protect
);
646 ret
+= nss_macsec_secy_rx_sc_anti_replay_window_set(drv
->secy_id
,
654 static int macsec_qca_delete_receive_sc(void *priv
, struct receive_sc
*sc
)
656 struct macsec_qca_data
*drv
= priv
;
658 fal_rx_prc_lut_t entry
;
659 u32 channel
= sc
->channel
;
661 wpa_printf(MSG_DEBUG
, "%s: channel=%d", __func__
, channel
);
664 os_memset(&entry
, 0, sizeof(entry
));
666 ret
+= nss_macsec_secy_rx_sc_del(drv
->secy_id
, channel
);
667 ret
+= nss_macsec_secy_rx_prc_lut_set(drv
->secy_id
, channel
, &entry
);
673 static int macsec_qca_create_receive_sa(void *priv
, struct receive_sa
*sa
)
675 struct macsec_qca_data
*drv
= priv
;
679 u32 channel
= sa
->sc
->channel
;
681 wpa_printf(MSG_DEBUG
, "%s, channel=%d, an=%d, lpn=0x%x",
682 __func__
, channel
, sa
->an
, sa
->lowest_pn
);
684 os_memset(&rx_sak
, 0, sizeof(rx_sak
));
685 for (i
= 0; i
< 16; i
++)
686 rx_sak
.sak
[i
] = sa
->pkey
->key
[15 - i
];
688 ret
+= nss_macsec_secy_rx_sa_create(drv
->secy_id
, channel
, sa
->an
);
689 ret
+= nss_macsec_secy_rx_sak_set(drv
->secy_id
, channel
, sa
->an
,
696 static int macsec_qca_enable_receive_sa(void *priv
, struct receive_sa
*sa
)
698 struct macsec_qca_data
*drv
= priv
;
700 u32 channel
= sa
->sc
->channel
;
703 wpa_printf(MSG_DEBUG
, "%s: channel=%d, an=%d", __func__
, channel
,
706 ret
+= nss_macsec_secy_rx_sa_en_set(drv
->secy_id
, channel
, sa
->an
,
713 static int macsec_qca_disable_receive_sa(void *priv
, struct receive_sa
*sa
)
715 struct macsec_qca_data
*drv
= priv
;
717 u32 channel
= sa
->sc
->channel
;
719 wpa_printf(MSG_DEBUG
, "%s: channel=%d, an=%d", __func__
, channel
,
722 ret
+= nss_macsec_secy_rx_sa_en_set(drv
->secy_id
, channel
, sa
->an
,
729 static int macsec_qca_get_available_transmit_sc(void *priv
, u32
*channel
)
731 struct macsec_qca_data
*drv
= priv
;
736 for (sc_ch
= 0; sc_ch
< MAXSC
; sc_ch
++) {
737 ret
= nss_macsec_secy_tx_sc_in_used_get(drv
->secy_id
, sc_ch
,
744 wpa_printf(MSG_DEBUG
, "%s: channel=%d",
750 wpa_printf(MSG_DEBUG
, "%s: no avaiable channel", __func__
);
756 static int macsec_qca_create_transmit_sc(void *priv
, struct transmit_sc
*sc
,
757 unsigned int conf_offset
)
759 struct macsec_qca_data
*drv
= priv
;
761 fal_tx_class_lut_t entry
;
762 u8 psci
[ETH_ALEN
+ 2];
763 u32 channel
= sc
->channel
;
765 wpa_printf(MSG_DEBUG
, "%s: channel=%d", __func__
, channel
);
768 os_memset(&entry
, 0, sizeof(entry
));
771 entry
.action
= FAL_TX_CLASS_ACTION_FORWARD
;
772 entry
.channel
= channel
;
774 os_memcpy(psci
, sc
->sci
.addr
, ETH_ALEN
);
775 psci
[6] = (sc
->sci
.port
>> 8) & 0xf;
776 psci
[7] = sc
->sci
.port
& 0xf;
778 ret
+= nss_macsec_secy_tx_class_lut_set(drv
->secy_id
, channel
, &entry
);
779 ret
+= nss_macsec_secy_tx_sc_create(drv
->secy_id
, channel
, psci
, 8);
780 ret
+= nss_macsec_secy_tx_sc_protect_set(drv
->secy_id
, channel
,
781 drv
->protect_frames
);
782 ret
+= nss_macsec_secy_tx_sc_confidentiality_offset_set(drv
->secy_id
,
790 static int macsec_qca_delete_transmit_sc(void *priv
, struct transmit_sc
*sc
)
792 struct macsec_qca_data
*drv
= priv
;
794 fal_tx_class_lut_t entry
;
795 u32 channel
= sc
->channel
;
797 wpa_printf(MSG_DEBUG
, "%s: channel=%d", __func__
, channel
);
800 os_memset(&entry
, 0, sizeof(entry
));
802 ret
+= nss_macsec_secy_tx_class_lut_set(drv
->secy_id
, channel
, &entry
);
803 ret
+= nss_macsec_secy_tx_sc_del(drv
->secy_id
, channel
);
809 static int macsec_qca_create_transmit_sa(void *priv
, struct transmit_sa
*sa
)
811 struct macsec_qca_data
*drv
= priv
;
816 u32 channel
= sa
->sc
->channel
;
818 wpa_printf(MSG_DEBUG
,
819 "%s: channel=%d, an=%d, next_pn=0x%x, confidentiality=%d",
820 __func__
, channel
, sa
->an
, sa
->next_pn
, sa
->confidentiality
);
822 if (drv
->always_include_sci
)
824 else if (drv
->use_es
)
826 else if (drv
->use_scb
)
829 if (sa
->confidentiality
)
830 tci
|= TCI_E
| TCI_C
;
832 os_memset(&tx_sak
, 0, sizeof(tx_sak
));
833 for (i
= 0; i
< 16; i
++)
834 tx_sak
.sak
[i
] = sa
->pkey
->key
[15 - i
];
836 ret
+= nss_macsec_secy_tx_sa_next_pn_set(drv
->secy_id
, channel
, sa
->an
,
838 ret
+= nss_macsec_secy_tx_sak_set(drv
->secy_id
, channel
, sa
->an
,
840 ret
+= nss_macsec_secy_tx_sc_tci_7_2_set(drv
->secy_id
, channel
,
842 ret
+= nss_macsec_secy_tx_sc_an_set(drv
->secy_id
, channel
, sa
->an
);
848 static int macsec_qca_enable_transmit_sa(void *priv
, struct transmit_sa
*sa
)
850 struct macsec_qca_data
*drv
= priv
;
852 u32 channel
= sa
->sc
->channel
;
855 wpa_printf(MSG_DEBUG
, "%s: channel=%d, an=%d", __func__
, channel
,
858 ret
+= nss_macsec_secy_tx_sa_en_set(drv
->secy_id
, channel
, sa
->an
,
865 static int macsec_qca_disable_transmit_sa(void *priv
, struct transmit_sa
*sa
)
867 struct macsec_qca_data
*drv
= priv
;
869 u32 channel
= sa
->sc
->channel
;
871 wpa_printf(MSG_DEBUG
, "%s: channel=%d, an=%d", __func__
, channel
,
874 ret
+= nss_macsec_secy_tx_sa_en_set(drv
->secy_id
, channel
, sa
->an
,
881 const struct wpa_driver_ops wpa_driver_macsec_qca_ops
= {
882 .name
= "macsec_qca",
883 .desc
= "QCA MACsec Ethernet driver",
884 .get_ssid
= macsec_qca_get_ssid
,
885 .get_bssid
= macsec_qca_get_bssid
,
886 .get_capa
= macsec_qca_get_capa
,
887 .init
= macsec_qca_init
,
888 .deinit
= macsec_qca_deinit
,
890 .macsec_init
= macsec_qca_macsec_init
,
891 .macsec_deinit
= macsec_qca_macsec_deinit
,
892 .enable_protect_frames
= macsec_qca_enable_protect_frames
,
893 .set_replay_protect
= macsec_qca_set_replay_protect
,
894 .set_current_cipher_suite
= macsec_qca_set_current_cipher_suite
,
895 .enable_controlled_port
= macsec_qca_enable_controlled_port
,
896 .get_receive_lowest_pn
= macsec_qca_get_receive_lowest_pn
,
897 .get_transmit_next_pn
= macsec_qca_get_transmit_next_pn
,
898 .set_transmit_next_pn
= macsec_qca_set_transmit_next_pn
,
899 .get_available_receive_sc
= macsec_qca_get_available_receive_sc
,
900 .create_receive_sc
= macsec_qca_create_receive_sc
,
901 .delete_receive_sc
= macsec_qca_delete_receive_sc
,
902 .create_receive_sa
= macsec_qca_create_receive_sa
,
903 .enable_receive_sa
= macsec_qca_enable_receive_sa
,
904 .disable_receive_sa
= macsec_qca_disable_receive_sa
,
905 .get_available_transmit_sc
= macsec_qca_get_available_transmit_sc
,
906 .create_transmit_sc
= macsec_qca_create_transmit_sc
,
907 .delete_transmit_sc
= macsec_qca_delete_transmit_sc
,
908 .create_transmit_sa
= macsec_qca_create_transmit_sa
,
909 .enable_transmit_sa
= macsec_qca_enable_transmit_sa
,
910 .disable_transmit_sa
= macsec_qca_disable_transmit_sa
,