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
, u32 channel
,
605 const u8
*sci_addr
, u16 sci_port
,
606 unsigned int conf_offset
,
609 struct macsec_qca_data
*drv
= priv
;
611 fal_rx_prc_lut_t entry
;
612 fal_rx_sc_validate_frame_e vf
;
613 enum validate_frames validate_frames
= validation
;
615 wpa_printf(MSG_DEBUG
, "%s: channel=%d", __func__
, channel
);
618 os_memset(&entry
, 0, sizeof(entry
));
620 os_memcpy(entry
.sci
, sci_addr
, ETH_ALEN
);
621 entry
.sci
[6] = (sci_port
>> 8) & 0xf;
622 entry
.sci
[7] = sci_port
& 0xf;
623 entry
.sci_mask
= 0xf;
626 entry
.channel
= channel
;
627 entry
.action
= FAL_RX_PRC_ACTION_PROCESS
;
628 entry
.offset
= conf_offset
;
630 /* rx validate frame */
631 if (validate_frames
== Strict
)
632 vf
= FAL_RX_SC_VALIDATE_FRAME_STRICT
;
633 else if (validate_frames
== Checked
)
634 vf
= FAL_RX_SC_VALIDATE_FRAME_CHECK
;
636 vf
= FAL_RX_SC_VALIDATE_FRAME_DISABLED
;
638 ret
+= nss_macsec_secy_rx_prc_lut_set(drv
->secy_id
, channel
, &entry
);
639 ret
+= nss_macsec_secy_rx_sc_create(drv
->secy_id
, channel
);
640 ret
+= nss_macsec_secy_rx_sc_validate_frame_set(drv
->secy_id
, channel
,
642 ret
+= nss_macsec_secy_rx_sc_replay_protect_set(drv
->secy_id
, channel
,
643 drv
->replay_protect
);
644 ret
+= nss_macsec_secy_rx_sc_anti_replay_window_set(drv
->secy_id
,
652 static int macsec_qca_delete_receive_sc(void *priv
, u32 channel
)
654 struct macsec_qca_data
*drv
= priv
;
656 fal_rx_prc_lut_t entry
;
658 wpa_printf(MSG_DEBUG
, "%s: channel=%d", __func__
, channel
);
661 os_memset(&entry
, 0, sizeof(entry
));
663 ret
+= nss_macsec_secy_rx_sc_del(drv
->secy_id
, channel
);
664 ret
+= nss_macsec_secy_rx_prc_lut_set(drv
->secy_id
, channel
, &entry
);
670 static int macsec_qca_create_receive_sa(void *priv
, u32 channel
, u8 an
,
671 u32 lowest_pn
, const u8
*sak
)
673 struct macsec_qca_data
*drv
= priv
;
678 wpa_printf(MSG_DEBUG
, "%s, channel=%d, an=%d, lpn=0x%x",
679 __func__
, channel
, an
, lowest_pn
);
681 os_memset(&rx_sak
, 0, sizeof(rx_sak
));
682 for (i
= 0; i
< 16; i
++)
683 rx_sak
.sak
[i
] = sak
[15 - i
];
685 ret
+= nss_macsec_secy_rx_sa_create(drv
->secy_id
, channel
, an
);
686 ret
+= nss_macsec_secy_rx_sak_set(drv
->secy_id
, channel
, an
, &rx_sak
);
692 static int macsec_qca_enable_receive_sa(void *priv
, u32 channel
, u8 an
)
694 struct macsec_qca_data
*drv
= priv
;
697 wpa_printf(MSG_DEBUG
, "%s: channel=%d, an=%d", __func__
, channel
, an
);
699 ret
+= nss_macsec_secy_rx_sa_en_set(drv
->secy_id
, channel
, an
, TRUE
);
705 static int macsec_qca_disable_receive_sa(void *priv
, u32 channel
, u8 an
)
707 struct macsec_qca_data
*drv
= priv
;
710 wpa_printf(MSG_DEBUG
, "%s: channel=%d, an=%d", __func__
, channel
, an
);
712 ret
+= nss_macsec_secy_rx_sa_en_set(drv
->secy_id
, channel
, an
, FALSE
);
718 static int macsec_qca_get_available_transmit_sc(void *priv
, u32
*channel
)
720 struct macsec_qca_data
*drv
= priv
;
725 for (sc_ch
= 0; sc_ch
< MAXSC
; sc_ch
++) {
726 ret
= nss_macsec_secy_tx_sc_in_used_get(drv
->secy_id
, sc_ch
,
733 wpa_printf(MSG_DEBUG
, "%s: channel=%d",
739 wpa_printf(MSG_DEBUG
, "%s: no avaiable channel", __func__
);
745 static int macsec_qca_create_transmit_sc(void *priv
, u32 channel
,
746 const u8
*sci_addr
, u16 sci_port
,
747 unsigned int conf_offset
)
749 struct macsec_qca_data
*drv
= priv
;
751 fal_tx_class_lut_t entry
;
752 u8 psci
[ETH_ALEN
+ 2];
754 wpa_printf(MSG_DEBUG
, "%s: channel=%d", __func__
, channel
);
757 os_memset(&entry
, 0, sizeof(entry
));
760 entry
.action
= FAL_TX_CLASS_ACTION_FORWARD
;
761 entry
.channel
= channel
;
763 os_memcpy(psci
, sci_addr
, ETH_ALEN
);
764 psci
[6] = (sci_port
>> 8) & 0xf;
765 psci
[7] = sci_port
& 0xf;
767 ret
+= nss_macsec_secy_tx_class_lut_set(drv
->secy_id
, channel
, &entry
);
768 ret
+= nss_macsec_secy_tx_sc_create(drv
->secy_id
, channel
, psci
, 8);
769 ret
+= nss_macsec_secy_tx_sc_protect_set(drv
->secy_id
, channel
,
770 drv
->protect_frames
);
771 ret
+= nss_macsec_secy_tx_sc_confidentiality_offset_set(drv
->secy_id
,
779 static int macsec_qca_delete_transmit_sc(void *priv
, u32 channel
)
781 struct macsec_qca_data
*drv
= priv
;
783 fal_tx_class_lut_t entry
;
785 wpa_printf(MSG_DEBUG
, "%s: channel=%d", __func__
, channel
);
788 os_memset(&entry
, 0, sizeof(entry
));
790 ret
+= nss_macsec_secy_tx_class_lut_set(drv
->secy_id
, channel
, &entry
);
791 ret
+= nss_macsec_secy_tx_sc_del(drv
->secy_id
, channel
);
797 static int macsec_qca_create_transmit_sa(void *priv
, struct transmit_sa
*sa
)
799 struct macsec_qca_data
*drv
= priv
;
804 u32 channel
= sa
->sc
->channel
;
806 wpa_printf(MSG_DEBUG
,
807 "%s: channel=%d, an=%d, next_pn=0x%x, confidentiality=%d",
808 __func__
, channel
, sa
->an
, sa
->next_pn
, sa
->confidentiality
);
810 if (drv
->always_include_sci
)
812 else if (drv
->use_es
)
814 else if (drv
->use_scb
)
817 if (sa
->confidentiality
)
818 tci
|= TCI_E
| TCI_C
;
820 os_memset(&tx_sak
, 0, sizeof(tx_sak
));
821 for (i
= 0; i
< 16; i
++)
822 tx_sak
.sak
[i
] = sa
->pkey
->key
[15 - i
];
824 ret
+= nss_macsec_secy_tx_sa_next_pn_set(drv
->secy_id
, channel
, sa
->an
,
826 ret
+= nss_macsec_secy_tx_sak_set(drv
->secy_id
, channel
, sa
->an
,
828 ret
+= nss_macsec_secy_tx_sc_tci_7_2_set(drv
->secy_id
, channel
,
830 ret
+= nss_macsec_secy_tx_sc_an_set(drv
->secy_id
, channel
, sa
->an
);
836 static int macsec_qca_enable_transmit_sa(void *priv
, struct transmit_sa
*sa
)
838 struct macsec_qca_data
*drv
= priv
;
840 u32 channel
= sa
->sc
->channel
;
843 wpa_printf(MSG_DEBUG
, "%s: channel=%d, an=%d", __func__
, channel
,
846 ret
+= nss_macsec_secy_tx_sa_en_set(drv
->secy_id
, channel
, sa
->an
,
853 static int macsec_qca_disable_transmit_sa(void *priv
, struct transmit_sa
*sa
)
855 struct macsec_qca_data
*drv
= priv
;
857 u32 channel
= sa
->sc
->channel
;
859 wpa_printf(MSG_DEBUG
, "%s: channel=%d, an=%d", __func__
, channel
,
862 ret
+= nss_macsec_secy_tx_sa_en_set(drv
->secy_id
, channel
, sa
->an
,
869 const struct wpa_driver_ops wpa_driver_macsec_qca_ops
= {
870 .name
= "macsec_qca",
871 .desc
= "QCA MACsec Ethernet driver",
872 .get_ssid
= macsec_qca_get_ssid
,
873 .get_bssid
= macsec_qca_get_bssid
,
874 .get_capa
= macsec_qca_get_capa
,
875 .init
= macsec_qca_init
,
876 .deinit
= macsec_qca_deinit
,
878 .macsec_init
= macsec_qca_macsec_init
,
879 .macsec_deinit
= macsec_qca_macsec_deinit
,
880 .enable_protect_frames
= macsec_qca_enable_protect_frames
,
881 .set_replay_protect
= macsec_qca_set_replay_protect
,
882 .set_current_cipher_suite
= macsec_qca_set_current_cipher_suite
,
883 .enable_controlled_port
= macsec_qca_enable_controlled_port
,
884 .get_receive_lowest_pn
= macsec_qca_get_receive_lowest_pn
,
885 .get_transmit_next_pn
= macsec_qca_get_transmit_next_pn
,
886 .set_transmit_next_pn
= macsec_qca_set_transmit_next_pn
,
887 .get_available_receive_sc
= macsec_qca_get_available_receive_sc
,
888 .create_receive_sc
= macsec_qca_create_receive_sc
,
889 .delete_receive_sc
= macsec_qca_delete_receive_sc
,
890 .create_receive_sa
= macsec_qca_create_receive_sa
,
891 .enable_receive_sa
= macsec_qca_enable_receive_sa
,
892 .disable_receive_sa
= macsec_qca_disable_receive_sa
,
893 .get_available_transmit_sc
= macsec_qca_get_available_transmit_sc
,
894 .create_transmit_sc
= macsec_qca_create_transmit_sc
,
895 .delete_transmit_sc
= macsec_qca_delete_transmit_sc
,
896 .create_transmit_sa
= macsec_qca_create_transmit_sa
,
897 .enable_transmit_sa
= macsec_qca_enable_transmit_sa
,
898 .disable_transmit_sa
= macsec_qca_disable_transmit_sa
,