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_get_capability(void *priv
, enum macsec_cap
*cap
)
463 wpa_printf(MSG_DEBUG
, "%s", __func__
);
465 *cap
= MACSEC_CAP_INTEG_AND_CONF_0_30_50
;
471 static int macsec_qca_enable_protect_frames(void *priv
, Boolean enabled
)
473 struct macsec_qca_data
*drv
= priv
;
476 wpa_printf(MSG_DEBUG
, "%s: enabled=%d", __func__
, enabled
);
478 drv
->protect_frames
= enabled
;
484 static int macsec_qca_set_replay_protect(void *priv
, Boolean enabled
,
487 struct macsec_qca_data
*drv
= priv
;
490 wpa_printf(MSG_DEBUG
, "%s: enabled=%d, win=%u",
491 __func__
, enabled
, window
);
493 drv
->replay_protect
= enabled
;
494 drv
->replay_window
= window
;
500 static int macsec_qca_set_current_cipher_suite(void *priv
, u64 cs
)
502 if (cs
!= CS_ID_GCM_AES_128
) {
503 wpa_printf(MSG_ERROR
,
504 "%s: NOT supported CipherSuite: %016" PRIx64
,
509 /* Support default Cipher Suite 0080020001000001 (GCM-AES-128) */
510 wpa_printf(MSG_DEBUG
, "%s: default support aes-gcm-128", __func__
);
516 static int macsec_qca_enable_controlled_port(void *priv
, Boolean enabled
)
518 struct macsec_qca_data
*drv
= priv
;
521 wpa_printf(MSG_DEBUG
, "%s: enable=%d", __func__
, enabled
);
523 ret
+= nss_macsec_secy_controlled_port_en_set(drv
->secy_id
, enabled
);
529 static int macsec_qca_get_receive_lowest_pn(void *priv
, struct receive_sa
*sa
)
531 struct macsec_qca_data
*drv
= priv
;
534 bool enabled
= FALSE
;
536 u32 channel
= sa
->sc
->channel
;
538 ret
+= nss_macsec_secy_rx_sa_next_pn_get(drv
->secy_id
, channel
, sa
->an
,
540 ret
+= nss_macsec_secy_rx_sc_replay_protect_get(drv
->secy_id
, channel
,
542 ret
+= nss_macsec_secy_rx_sc_anti_replay_window_get(drv
->secy_id
,
546 sa
->lowest_pn
= (next_pn
> win
) ? (next_pn
- win
) : 1;
548 sa
->lowest_pn
= next_pn
;
550 wpa_printf(MSG_DEBUG
, "%s: lpn=0x%x", __func__
, sa
->lowest_pn
);
556 static int macsec_qca_get_transmit_next_pn(void *priv
, struct transmit_sa
*sa
)
558 struct macsec_qca_data
*drv
= priv
;
560 u32 channel
= sa
->sc
->channel
;
562 ret
+= nss_macsec_secy_tx_sa_next_pn_get(drv
->secy_id
, channel
, sa
->an
,
565 wpa_printf(MSG_DEBUG
, "%s: npn=0x%x", __func__
, sa
->next_pn
);
571 int macsec_qca_set_transmit_next_pn(void *priv
, struct transmit_sa
*sa
)
573 struct macsec_qca_data
*drv
= priv
;
575 u32 channel
= sa
->sc
->channel
;
578 ret
+= nss_macsec_secy_tx_sa_next_pn_set(drv
->secy_id
, channel
, sa
->an
,
581 wpa_printf(MSG_INFO
, "%s: npn=0x%x", __func__
, sa
->next_pn
);
587 static int macsec_qca_get_available_receive_sc(void *priv
, u32
*channel
)
589 struct macsec_qca_data
*drv
= priv
;
594 for (sc_ch
= 0; sc_ch
< MAXSC
; sc_ch
++) {
595 ret
= nss_macsec_secy_rx_sc_in_used_get(drv
->secy_id
, sc_ch
,
602 wpa_printf(MSG_DEBUG
, "%s: channel=%d",
608 wpa_printf(MSG_DEBUG
, "%s: no available channel", __func__
);
614 static int macsec_qca_create_receive_sc(void *priv
, struct receive_sc
*sc
,
615 unsigned int conf_offset
,
618 struct macsec_qca_data
*drv
= priv
;
620 fal_rx_prc_lut_t entry
;
621 fal_rx_sc_validate_frame_e vf
;
622 enum validate_frames validate_frames
= validation
;
623 u32 channel
= sc
->channel
;
624 const u8
*sci_addr
= sc
->sci
.addr
;
625 u16 sci_port
= be_to_host16(sc
->sci
.port
);
627 wpa_printf(MSG_DEBUG
, "%s: channel=%d", __func__
, channel
);
630 os_memset(&entry
, 0, sizeof(entry
));
632 os_memcpy(entry
.sci
, sci_addr
, ETH_ALEN
);
633 entry
.sci
[6] = (sci_port
>> 8) & 0xf;
634 entry
.sci
[7] = sci_port
& 0xf;
635 entry
.sci_mask
= 0xf;
638 entry
.channel
= channel
;
639 entry
.action
= FAL_RX_PRC_ACTION_PROCESS
;
640 entry
.offset
= conf_offset
;
642 /* rx validate frame */
643 if (validate_frames
== Strict
)
644 vf
= FAL_RX_SC_VALIDATE_FRAME_STRICT
;
645 else if (validate_frames
== Checked
)
646 vf
= FAL_RX_SC_VALIDATE_FRAME_CHECK
;
648 vf
= FAL_RX_SC_VALIDATE_FRAME_DISABLED
;
650 ret
+= nss_macsec_secy_rx_prc_lut_set(drv
->secy_id
, channel
, &entry
);
651 ret
+= nss_macsec_secy_rx_sc_create(drv
->secy_id
, channel
);
652 ret
+= nss_macsec_secy_rx_sc_validate_frame_set(drv
->secy_id
, channel
,
654 ret
+= nss_macsec_secy_rx_sc_replay_protect_set(drv
->secy_id
, channel
,
655 drv
->replay_protect
);
656 ret
+= nss_macsec_secy_rx_sc_anti_replay_window_set(drv
->secy_id
,
664 static int macsec_qca_delete_receive_sc(void *priv
, struct receive_sc
*sc
)
666 struct macsec_qca_data
*drv
= priv
;
668 fal_rx_prc_lut_t entry
;
669 u32 channel
= sc
->channel
;
671 wpa_printf(MSG_DEBUG
, "%s: channel=%d", __func__
, channel
);
674 os_memset(&entry
, 0, sizeof(entry
));
676 ret
+= nss_macsec_secy_rx_sc_del(drv
->secy_id
, channel
);
677 ret
+= nss_macsec_secy_rx_prc_lut_set(drv
->secy_id
, channel
, &entry
);
683 static int macsec_qca_create_receive_sa(void *priv
, struct receive_sa
*sa
)
685 struct macsec_qca_data
*drv
= priv
;
689 u32 channel
= sa
->sc
->channel
;
691 wpa_printf(MSG_DEBUG
, "%s, channel=%d, an=%d, lpn=0x%x",
692 __func__
, channel
, sa
->an
, sa
->lowest_pn
);
694 os_memset(&rx_sak
, 0, sizeof(rx_sak
));
695 for (i
= 0; i
< 16; i
++)
696 rx_sak
.sak
[i
] = sa
->pkey
->key
[15 - i
];
698 ret
+= nss_macsec_secy_rx_sa_create(drv
->secy_id
, channel
, sa
->an
);
699 ret
+= nss_macsec_secy_rx_sak_set(drv
->secy_id
, channel
, sa
->an
,
706 static int macsec_qca_enable_receive_sa(void *priv
, struct receive_sa
*sa
)
708 struct macsec_qca_data
*drv
= priv
;
710 u32 channel
= sa
->sc
->channel
;
713 wpa_printf(MSG_DEBUG
, "%s: channel=%d, an=%d", __func__
, channel
,
716 ret
+= nss_macsec_secy_rx_sa_en_set(drv
->secy_id
, channel
, sa
->an
,
723 static int macsec_qca_disable_receive_sa(void *priv
, struct receive_sa
*sa
)
725 struct macsec_qca_data
*drv
= priv
;
727 u32 channel
= sa
->sc
->channel
;
729 wpa_printf(MSG_DEBUG
, "%s: channel=%d, an=%d", __func__
, channel
,
732 ret
+= nss_macsec_secy_rx_sa_en_set(drv
->secy_id
, channel
, sa
->an
,
739 static int macsec_qca_get_available_transmit_sc(void *priv
, u32
*channel
)
741 struct macsec_qca_data
*drv
= priv
;
746 for (sc_ch
= 0; sc_ch
< MAXSC
; sc_ch
++) {
747 ret
= nss_macsec_secy_tx_sc_in_used_get(drv
->secy_id
, sc_ch
,
754 wpa_printf(MSG_DEBUG
, "%s: channel=%d",
760 wpa_printf(MSG_DEBUG
, "%s: no avaiable channel", __func__
);
766 static int macsec_qca_create_transmit_sc(void *priv
, struct transmit_sc
*sc
,
767 unsigned int conf_offset
)
769 struct macsec_qca_data
*drv
= priv
;
771 fal_tx_class_lut_t entry
;
772 u8 psci
[ETH_ALEN
+ 2];
773 u32 channel
= sc
->channel
;
775 wpa_printf(MSG_DEBUG
, "%s: channel=%d", __func__
, channel
);
778 os_memset(&entry
, 0, sizeof(entry
));
781 entry
.action
= FAL_TX_CLASS_ACTION_FORWARD
;
782 entry
.channel
= channel
;
784 os_memcpy(psci
, sc
->sci
.addr
, ETH_ALEN
);
785 psci
[6] = (sc
->sci
.port
>> 8) & 0xf;
786 psci
[7] = sc
->sci
.port
& 0xf;
788 ret
+= nss_macsec_secy_tx_class_lut_set(drv
->secy_id
, channel
, &entry
);
789 ret
+= nss_macsec_secy_tx_sc_create(drv
->secy_id
, channel
, psci
, 8);
790 ret
+= nss_macsec_secy_tx_sc_protect_set(drv
->secy_id
, channel
,
791 drv
->protect_frames
);
792 ret
+= nss_macsec_secy_tx_sc_confidentiality_offset_set(drv
->secy_id
,
800 static int macsec_qca_delete_transmit_sc(void *priv
, struct transmit_sc
*sc
)
802 struct macsec_qca_data
*drv
= priv
;
804 fal_tx_class_lut_t entry
;
805 u32 channel
= sc
->channel
;
807 wpa_printf(MSG_DEBUG
, "%s: channel=%d", __func__
, channel
);
810 os_memset(&entry
, 0, sizeof(entry
));
812 ret
+= nss_macsec_secy_tx_class_lut_set(drv
->secy_id
, channel
, &entry
);
813 ret
+= nss_macsec_secy_tx_sc_del(drv
->secy_id
, channel
);
819 static int macsec_qca_create_transmit_sa(void *priv
, struct transmit_sa
*sa
)
821 struct macsec_qca_data
*drv
= priv
;
826 u32 channel
= sa
->sc
->channel
;
828 wpa_printf(MSG_DEBUG
,
829 "%s: channel=%d, an=%d, next_pn=0x%x, confidentiality=%d",
830 __func__
, channel
, sa
->an
, sa
->next_pn
, sa
->confidentiality
);
832 if (drv
->always_include_sci
)
834 else if (drv
->use_es
)
836 else if (drv
->use_scb
)
839 if (sa
->confidentiality
)
840 tci
|= TCI_E
| TCI_C
;
842 os_memset(&tx_sak
, 0, sizeof(tx_sak
));
843 for (i
= 0; i
< 16; i
++)
844 tx_sak
.sak
[i
] = sa
->pkey
->key
[15 - i
];
846 ret
+= nss_macsec_secy_tx_sa_next_pn_set(drv
->secy_id
, channel
, sa
->an
,
848 ret
+= nss_macsec_secy_tx_sak_set(drv
->secy_id
, channel
, sa
->an
,
850 ret
+= nss_macsec_secy_tx_sc_tci_7_2_set(drv
->secy_id
, channel
,
852 ret
+= nss_macsec_secy_tx_sc_an_set(drv
->secy_id
, channel
, sa
->an
);
858 static int macsec_qca_enable_transmit_sa(void *priv
, struct transmit_sa
*sa
)
860 struct macsec_qca_data
*drv
= priv
;
862 u32 channel
= sa
->sc
->channel
;
865 wpa_printf(MSG_DEBUG
, "%s: channel=%d, an=%d", __func__
, channel
,
868 ret
+= nss_macsec_secy_tx_sa_en_set(drv
->secy_id
, channel
, sa
->an
,
875 static int macsec_qca_disable_transmit_sa(void *priv
, struct transmit_sa
*sa
)
877 struct macsec_qca_data
*drv
= priv
;
879 u32 channel
= sa
->sc
->channel
;
881 wpa_printf(MSG_DEBUG
, "%s: channel=%d, an=%d", __func__
, channel
,
884 ret
+= nss_macsec_secy_tx_sa_en_set(drv
->secy_id
, channel
, sa
->an
,
891 const struct wpa_driver_ops wpa_driver_macsec_qca_ops
= {
892 .name
= "macsec_qca",
893 .desc
= "QCA MACsec Ethernet driver",
894 .get_ssid
= macsec_qca_get_ssid
,
895 .get_bssid
= macsec_qca_get_bssid
,
896 .get_capa
= macsec_qca_get_capa
,
897 .init
= macsec_qca_init
,
898 .deinit
= macsec_qca_deinit
,
900 .macsec_init
= macsec_qca_macsec_init
,
901 .macsec_deinit
= macsec_qca_macsec_deinit
,
902 .macsec_get_capability
= macsec_qca_get_capability
,
903 .enable_protect_frames
= macsec_qca_enable_protect_frames
,
904 .set_replay_protect
= macsec_qca_set_replay_protect
,
905 .set_current_cipher_suite
= macsec_qca_set_current_cipher_suite
,
906 .enable_controlled_port
= macsec_qca_enable_controlled_port
,
907 .get_receive_lowest_pn
= macsec_qca_get_receive_lowest_pn
,
908 .get_transmit_next_pn
= macsec_qca_get_transmit_next_pn
,
909 .set_transmit_next_pn
= macsec_qca_set_transmit_next_pn
,
910 .get_available_receive_sc
= macsec_qca_get_available_receive_sc
,
911 .create_receive_sc
= macsec_qca_create_receive_sc
,
912 .delete_receive_sc
= macsec_qca_delete_receive_sc
,
913 .create_receive_sa
= macsec_qca_create_receive_sa
,
914 .enable_receive_sa
= macsec_qca_enable_receive_sa
,
915 .disable_receive_sa
= macsec_qca_disable_receive_sa
,
916 .get_available_transmit_sc
= macsec_qca_get_available_transmit_sc
,
917 .create_transmit_sc
= macsec_qca_create_transmit_sc
,
918 .delete_transmit_sc
= macsec_qca_delete_transmit_sc
,
919 .create_transmit_sa
= macsec_qca_create_transmit_sa
,
920 .enable_transmit_sa
= macsec_qca_enable_transmit_sa
,
921 .disable_transmit_sa
= macsec_qca_disable_transmit_sa
,