xref: /freebsd/contrib/wpa/src/drivers/driver_macsec_qca.c (revision a90b9d0159070121c221b966469c3e36d912bf82)
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.
6206b73d0SCy Schubert  * Copyright (c) 2019, The Linux Foundation
75b9c547cSRui Paulo  *
85b9c547cSRui Paulo  * This software may be distributed under the terms of the BSD license.
95b9c547cSRui Paulo  * See README for more details.
105b9c547cSRui Paulo  */
115b9c547cSRui Paulo 
125b9c547cSRui Paulo #include "includes.h"
135b9c547cSRui Paulo #include <sys/ioctl.h>
145b9c547cSRui Paulo #include <net/if.h>
15780fb4a2SCy Schubert #include <inttypes.h>
165b9c547cSRui Paulo #ifdef __linux__
175b9c547cSRui Paulo #include <netpacket/packet.h>
185b9c547cSRui Paulo #include <net/if_arp.h>
195b9c547cSRui Paulo #include <net/if.h>
205b9c547cSRui Paulo #endif /* __linux__ */
215b9c547cSRui Paulo #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
225b9c547cSRui Paulo #include <net/if_dl.h>
235b9c547cSRui Paulo #include <net/if_media.h>
245b9c547cSRui Paulo #endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) */
255b9c547cSRui Paulo #ifdef __sun__
265b9c547cSRui Paulo #include <sys/sockio.h>
275b9c547cSRui Paulo #endif /* __sun__ */
285b9c547cSRui Paulo 
295b9c547cSRui Paulo #include "utils/common.h"
305b9c547cSRui Paulo #include "utils/eloop.h"
315b9c547cSRui Paulo #include "common/defs.h"
325b9c547cSRui Paulo #include "common/ieee802_1x_defs.h"
33206b73d0SCy Schubert #include "common/eapol_common.h"
3485732ac8SCy Schubert #include "pae/ieee802_1x_kay.h"
355b9c547cSRui Paulo #include "driver.h"
3685732ac8SCy Schubert #include "driver_wired_common.h"
375b9c547cSRui Paulo 
385b9c547cSRui Paulo #include "nss_macsec_secy.h"
395b9c547cSRui Paulo #include "nss_macsec_secy_rx.h"
405b9c547cSRui Paulo #include "nss_macsec_secy_tx.h"
415b9c547cSRui Paulo 
425b9c547cSRui Paulo #define MAXSC 16
435b9c547cSRui Paulo 
4485732ac8SCy Schubert #define SAK_128_LEN	16
4585732ac8SCy Schubert #define SAK_256_LEN	32
4685732ac8SCy Schubert 
475b9c547cSRui Paulo /* TCI field definition */
485b9c547cSRui Paulo #define TCI_ES                0x40
495b9c547cSRui Paulo #define TCI_SC                0x20
505b9c547cSRui Paulo #define TCI_SCB               0x10
515b9c547cSRui Paulo #define TCI_E                 0x08
525b9c547cSRui Paulo #define TCI_C                 0x04
535b9c547cSRui Paulo 
545b9c547cSRui Paulo #ifdef _MSC_VER
555b9c547cSRui Paulo #pragma pack(push, 1)
565b9c547cSRui Paulo #endif /* _MSC_VER */
575b9c547cSRui Paulo 
585b9c547cSRui Paulo #ifdef _MSC_VER
595b9c547cSRui Paulo #pragma pack(pop)
605b9c547cSRui Paulo #endif /* _MSC_VER */
615b9c547cSRui Paulo 
6285732ac8SCy Schubert struct channel_map {
6385732ac8SCy Schubert 	struct ieee802_1x_mka_sci sci;
6485732ac8SCy Schubert };
655b9c547cSRui Paulo 
665b9c547cSRui Paulo struct macsec_qca_data {
6785732ac8SCy Schubert 	struct driver_wired_common_data common;
685b9c547cSRui Paulo 
69206b73d0SCy Schubert 	int use_pae_group_addr;
7085732ac8SCy Schubert 	u32 secy_id;
715b9c547cSRui Paulo 
725b9c547cSRui Paulo 	/* shadow */
73c1d255d3SCy Schubert 	bool always_include_sci;
74c1d255d3SCy Schubert 	bool use_es;
75c1d255d3SCy Schubert 	bool use_scb;
76c1d255d3SCy Schubert 	bool protect_frames;
77c1d255d3SCy Schubert 	bool replay_protect;
785b9c547cSRui Paulo 	u32 replay_window;
7985732ac8SCy Schubert 
8085732ac8SCy Schubert 	struct channel_map receive_channel_map[MAXSC];
8185732ac8SCy Schubert 	struct channel_map transmit_channel_map[MAXSC];
825b9c547cSRui Paulo };
835b9c547cSRui Paulo 
845b9c547cSRui Paulo 
__macsec_drv_init(struct macsec_qca_data * drv)855b9c547cSRui Paulo static void __macsec_drv_init(struct macsec_qca_data *drv)
865b9c547cSRui Paulo {
875b9c547cSRui Paulo 	int ret = 0;
885b9c547cSRui Paulo 	fal_rx_ctl_filt_t rx_ctl_filt;
895b9c547cSRui Paulo 	fal_tx_ctl_filt_t tx_ctl_filt;
905b9c547cSRui Paulo 
915b9c547cSRui Paulo 	wpa_printf(MSG_INFO, "%s: secy_id=%d", __func__, drv->secy_id);
925b9c547cSRui Paulo 
935b9c547cSRui Paulo 	/* Enable Secy and Let EAPoL bypass */
94c1d255d3SCy Schubert 	ret = nss_macsec_secy_en_set(drv->secy_id, true);
955b9c547cSRui Paulo 	if (ret)
965b9c547cSRui Paulo 		wpa_printf(MSG_ERROR, "nss_macsec_secy_en_set: FAIL");
975b9c547cSRui Paulo 
985b9c547cSRui Paulo 	ret = nss_macsec_secy_sc_sa_mapping_mode_set(drv->secy_id,
995b9c547cSRui Paulo 						     FAL_SC_SA_MAP_1_4);
1005b9c547cSRui Paulo 	if (ret)
1015b9c547cSRui Paulo 		wpa_printf(MSG_ERROR,
1025b9c547cSRui Paulo 			   "nss_macsec_secy_sc_sa_mapping_mode_set: FAIL");
1035b9c547cSRui Paulo 
1045b9c547cSRui Paulo 	os_memset(&rx_ctl_filt, 0, sizeof(rx_ctl_filt));
1055b9c547cSRui Paulo 	rx_ctl_filt.bypass = 1;
1065b9c547cSRui Paulo 	rx_ctl_filt.match_type = IG_CTL_COMPARE_ETHER_TYPE;
1075b9c547cSRui Paulo 	rx_ctl_filt.match_mask = 0xffff;
1085b9c547cSRui Paulo 	rx_ctl_filt.ether_type_da_range = 0x888e;
1095b9c547cSRui Paulo 	ret = nss_macsec_secy_rx_ctl_filt_set(drv->secy_id, 0, &rx_ctl_filt);
1105b9c547cSRui Paulo 	if (ret)
1115b9c547cSRui Paulo 		wpa_printf(MSG_ERROR, "nss_macsec_secy_rx_ctl_filt_set: FAIL");
1125b9c547cSRui Paulo 
1135b9c547cSRui Paulo 	os_memset(&tx_ctl_filt, 0, sizeof(tx_ctl_filt));
1145b9c547cSRui Paulo 	tx_ctl_filt.bypass = 1;
1155b9c547cSRui Paulo 	tx_ctl_filt.match_type = EG_CTL_COMPARE_ETHER_TYPE;
1165b9c547cSRui Paulo 	tx_ctl_filt.match_mask = 0xffff;
1175b9c547cSRui Paulo 	tx_ctl_filt.ether_type_da_range = 0x888e;
1185b9c547cSRui Paulo 	ret = nss_macsec_secy_tx_ctl_filt_set(drv->secy_id, 0, &tx_ctl_filt);
1195b9c547cSRui Paulo 	if (ret)
1205b9c547cSRui Paulo 		wpa_printf(MSG_ERROR, "nss_macsec_secy_tx_ctl_filt_set: FAIL");
1215b9c547cSRui Paulo }
1225b9c547cSRui Paulo 
1235b9c547cSRui Paulo 
__macsec_drv_deinit(struct macsec_qca_data * drv)1245b9c547cSRui Paulo static void __macsec_drv_deinit(struct macsec_qca_data *drv)
1255b9c547cSRui Paulo {
126c1d255d3SCy Schubert 	nss_macsec_secy_en_set(drv->secy_id, false);
1275b9c547cSRui Paulo 	nss_macsec_secy_rx_sc_del_all(drv->secy_id);
1285b9c547cSRui Paulo 	nss_macsec_secy_tx_sc_del_all(drv->secy_id);
1295b9c547cSRui Paulo }
1305b9c547cSRui Paulo 
1315b9c547cSRui Paulo 
132206b73d0SCy Schubert #ifdef __linux__
133206b73d0SCy Schubert 
macsec_qca_handle_data(void * ctx,unsigned char * buf,size_t len)134206b73d0SCy Schubert static void macsec_qca_handle_data(void *ctx, unsigned char *buf, size_t len)
135206b73d0SCy Schubert {
136206b73d0SCy Schubert #ifdef HOSTAPD
137206b73d0SCy Schubert 	struct ieee8023_hdr *hdr;
138206b73d0SCy Schubert 	u8 *pos, *sa;
139206b73d0SCy Schubert 	size_t left;
140206b73d0SCy Schubert 	union wpa_event_data event;
141206b73d0SCy Schubert 
142206b73d0SCy Schubert 	/* at least 6 bytes src macaddress, 6 bytes dst macaddress
143206b73d0SCy Schubert 	 * and 2 bytes ethertype
144206b73d0SCy Schubert 	*/
145206b73d0SCy Schubert 	if (len < 14) {
146206b73d0SCy Schubert 		wpa_printf(MSG_MSGDUMP,
147206b73d0SCy Schubert 			   "macsec_qca_handle_data: too short (%lu)",
148206b73d0SCy Schubert 			   (unsigned long) len);
149206b73d0SCy Schubert 		return;
150206b73d0SCy Schubert 	}
151206b73d0SCy Schubert 	hdr = (struct ieee8023_hdr *) buf;
152206b73d0SCy Schubert 
153206b73d0SCy Schubert 	switch (ntohs(hdr->ethertype)) {
154206b73d0SCy Schubert 	case ETH_P_PAE:
155206b73d0SCy Schubert 		wpa_printf(MSG_MSGDUMP, "Received EAPOL packet");
156206b73d0SCy Schubert 		sa = hdr->src;
157206b73d0SCy Schubert 		os_memset(&event, 0, sizeof(event));
158206b73d0SCy Schubert 		event.new_sta.addr = sa;
159206b73d0SCy Schubert 		wpa_supplicant_event(ctx, EVENT_NEW_STA, &event);
160206b73d0SCy Schubert 
161206b73d0SCy Schubert 		pos = (u8 *) (hdr + 1);
162206b73d0SCy Schubert 		left = len - sizeof(*hdr);
163206b73d0SCy Schubert 		drv_event_eapol_rx(ctx, sa, pos, left);
164206b73d0SCy Schubert 		break;
165206b73d0SCy Schubert 	default:
166206b73d0SCy Schubert 		wpa_printf(MSG_DEBUG, "Unknown ethertype 0x%04x in data frame",
167206b73d0SCy Schubert 			   ntohs(hdr->ethertype));
168206b73d0SCy Schubert 		break;
169206b73d0SCy Schubert 	}
170206b73d0SCy Schubert #endif /* HOSTAPD */
171206b73d0SCy Schubert }
172206b73d0SCy Schubert 
173206b73d0SCy Schubert 
macsec_qca_handle_read(int sock,void * eloop_ctx,void * sock_ctx)174206b73d0SCy Schubert static void macsec_qca_handle_read(int sock, void *eloop_ctx, void *sock_ctx)
175206b73d0SCy Schubert {
176206b73d0SCy Schubert 	int len;
177206b73d0SCy Schubert 	unsigned char buf[3000];
178206b73d0SCy Schubert 
179206b73d0SCy Schubert 	len = recv(sock, buf, sizeof(buf), 0);
180206b73d0SCy Schubert 	if (len < 0) {
181206b73d0SCy Schubert 		wpa_printf(MSG_ERROR, "macsec_qca: recv: %s", strerror(errno));
182206b73d0SCy Schubert 		return;
183206b73d0SCy Schubert 	}
184206b73d0SCy Schubert 
185206b73d0SCy Schubert 	macsec_qca_handle_data(eloop_ctx, buf, len);
186206b73d0SCy Schubert }
187206b73d0SCy Schubert 
188206b73d0SCy Schubert #endif /* __linux__ */
189206b73d0SCy Schubert 
190206b73d0SCy Schubert 
macsec_qca_init_sockets(struct macsec_qca_data * drv,u8 * own_addr)191206b73d0SCy Schubert static int macsec_qca_init_sockets(struct macsec_qca_data *drv, u8 *own_addr)
192206b73d0SCy Schubert {
193206b73d0SCy Schubert #ifdef __linux__
194206b73d0SCy Schubert 	struct ifreq ifr;
195206b73d0SCy Schubert 	struct sockaddr_ll addr;
196206b73d0SCy Schubert 
197206b73d0SCy Schubert 	drv->common.sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_PAE));
198206b73d0SCy Schubert 	if (drv->common.sock < 0) {
199206b73d0SCy Schubert 		wpa_printf(MSG_ERROR, "socket[PF_PACKET,SOCK_RAW]: %s",
200206b73d0SCy Schubert 			   strerror(errno));
201206b73d0SCy Schubert 		return -1;
202206b73d0SCy Schubert 	}
203206b73d0SCy Schubert 
204206b73d0SCy Schubert 	if (eloop_register_read_sock(drv->common.sock, macsec_qca_handle_read,
205206b73d0SCy Schubert 				     drv->common.ctx, NULL)) {
206206b73d0SCy Schubert 		wpa_printf(MSG_INFO, "Could not register read socket");
207206b73d0SCy Schubert 		return -1;
208206b73d0SCy Schubert 	}
209206b73d0SCy Schubert 
210206b73d0SCy Schubert 	os_memset(&ifr, 0, sizeof(ifr));
211206b73d0SCy Schubert 	os_strlcpy(ifr.ifr_name, drv->common.ifname, sizeof(ifr.ifr_name));
212206b73d0SCy Schubert 	if (ioctl(drv->common.sock, SIOCGIFINDEX, &ifr) != 0) {
213206b73d0SCy Schubert 		wpa_printf(MSG_ERROR, "ioctl(SIOCGIFINDEX): %s",
214206b73d0SCy Schubert 			   strerror(errno));
215206b73d0SCy Schubert 		return -1;
216206b73d0SCy Schubert 	}
217206b73d0SCy Schubert 
218206b73d0SCy Schubert 	os_memset(&addr, 0, sizeof(addr));
219206b73d0SCy Schubert 	addr.sll_family = AF_PACKET;
220206b73d0SCy Schubert 	addr.sll_ifindex = ifr.ifr_ifindex;
221206b73d0SCy Schubert 	wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d",
222206b73d0SCy Schubert 		   addr.sll_ifindex);
223206b73d0SCy Schubert 
224206b73d0SCy Schubert 	if (bind(drv->common.sock, (struct sockaddr *) &addr,
225206b73d0SCy Schubert 		 sizeof(addr)) < 0) {
226206b73d0SCy Schubert 		wpa_printf(MSG_ERROR, "macsec_qca: bind: %s", strerror(errno));
227206b73d0SCy Schubert 		return -1;
228206b73d0SCy Schubert 	}
229206b73d0SCy Schubert 
230206b73d0SCy Schubert 	/* filter multicast address */
231206b73d0SCy Schubert 	if (wired_multicast_membership(drv->common.sock, ifr.ifr_ifindex,
232206b73d0SCy Schubert 				       pae_group_addr, 1) < 0) {
233206b73d0SCy Schubert 		wpa_printf(MSG_ERROR,
234206b73d0SCy Schubert 			"macsec_qca_init_sockets: Failed to add multicast group membership");
235206b73d0SCy Schubert 		return -1;
236206b73d0SCy Schubert 	}
237206b73d0SCy Schubert 
238206b73d0SCy Schubert 	os_memset(&ifr, 0, sizeof(ifr));
239206b73d0SCy Schubert 	os_strlcpy(ifr.ifr_name, drv->common.ifname, sizeof(ifr.ifr_name));
240206b73d0SCy Schubert 	if (ioctl(drv->common.sock, SIOCGIFHWADDR, &ifr) != 0) {
241206b73d0SCy Schubert 		wpa_printf(MSG_ERROR, "ioctl(SIOCGIFHWADDR): %s",
242206b73d0SCy Schubert 			   strerror(errno));
243206b73d0SCy Schubert 		return -1;
244206b73d0SCy Schubert 	}
245206b73d0SCy Schubert 
246206b73d0SCy Schubert 	if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
247206b73d0SCy Schubert 		wpa_printf(MSG_INFO, "Invalid HW-addr family 0x%04x",
248206b73d0SCy Schubert 			   ifr.ifr_hwaddr.sa_family);
249206b73d0SCy Schubert 		return -1;
250206b73d0SCy Schubert 	}
251206b73d0SCy Schubert 	os_memcpy(own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
252206b73d0SCy Schubert 
253206b73d0SCy Schubert 	return 0;
254206b73d0SCy Schubert #else /* __linux__ */
255206b73d0SCy Schubert 	return -1;
256206b73d0SCy Schubert #endif /* __linux__ */
257206b73d0SCy Schubert }
258206b73d0SCy Schubert 
259206b73d0SCy Schubert 
macsec_qca_secy_id_get(const char * ifname,u32 * secy_id)2604b72b91aSCy Schubert static int macsec_qca_secy_id_get(const char *ifname, u32 *secy_id)
2614b72b91aSCy Schubert {
2624b72b91aSCy Schubert #ifdef NSS_MACSEC_SECY_ID_GET_FUNC
2634b72b91aSCy Schubert 	/* Get secy id from nss macsec driver */
2644b72b91aSCy Schubert 	return nss_macsec_secy_id_get((u8 *) ifname, secy_id);
2654b72b91aSCy Schubert #else /* NSS_MACSEC_SECY_ID_GET_FUNC */
2664b72b91aSCy Schubert 	/* Board specific settings */
2674b72b91aSCy Schubert 	if (os_strcmp(ifname, "eth2") == 0) {
2684b72b91aSCy Schubert 		*secy_id = 1;
2694b72b91aSCy Schubert 	} else if (os_strcmp(ifname, "eth3") == 0) {
2704b72b91aSCy Schubert 		*secy_id = 2;
2714b72b91aSCy Schubert 	} else if (os_strcmp(ifname, "eth4") == 0 ||
2724b72b91aSCy Schubert 		   os_strcmp(ifname, "eth0") == 0) {
2734b72b91aSCy Schubert 		*secy_id = 0;
2744b72b91aSCy Schubert 	} else if (os_strcmp(ifname, "eth5") == 0 ||
2754b72b91aSCy Schubert 		   os_strcmp(ifname, "eth1") == 0) {
2764b72b91aSCy Schubert 		*secy_id = 1;
2774b72b91aSCy Schubert 	} else {
2784b72b91aSCy Schubert 		*secy_id = -1;
2794b72b91aSCy Schubert 		return -1;
2804b72b91aSCy Schubert 	}
2814b72b91aSCy Schubert 
2824b72b91aSCy Schubert 	return 0;
2834b72b91aSCy Schubert #endif /* NSS_MACSEC_SECY_ID_GET_FUNC */
2844b72b91aSCy Schubert }
2854b72b91aSCy Schubert 
2864b72b91aSCy Schubert 
macsec_qca_init(void * ctx,const char * ifname)2875b9c547cSRui Paulo static void * macsec_qca_init(void *ctx, const char *ifname)
2885b9c547cSRui Paulo {
2895b9c547cSRui Paulo 	struct macsec_qca_data *drv;
2905b9c547cSRui Paulo 
2915b9c547cSRui Paulo 	drv = os_zalloc(sizeof(*drv));
2925b9c547cSRui Paulo 	if (drv == NULL)
2935b9c547cSRui Paulo 		return NULL;
2945b9c547cSRui Paulo 
2954b72b91aSCy Schubert 	if (macsec_qca_secy_id_get(ifname, &drv->secy_id)) {
2964b72b91aSCy Schubert 		wpa_printf(MSG_ERROR,
2974b72b91aSCy Schubert 			   "macsec_qca: Failed to get secy_id for %s", ifname);
2984b72b91aSCy Schubert 		os_free(drv);
2994b72b91aSCy Schubert 		return NULL;
3004b72b91aSCy Schubert 	}
3015b9c547cSRui Paulo 
30285732ac8SCy Schubert 	if (driver_wired_init_common(&drv->common, ifname, ctx) < 0) {
3035b9c547cSRui Paulo 		os_free(drv);
3045b9c547cSRui Paulo 		return NULL;
3055b9c547cSRui Paulo 	}
3065b9c547cSRui Paulo 
3075b9c547cSRui Paulo 	return drv;
3085b9c547cSRui Paulo }
3095b9c547cSRui Paulo 
3105b9c547cSRui Paulo 
macsec_qca_deinit(void * priv)3115b9c547cSRui Paulo static void macsec_qca_deinit(void *priv)
3125b9c547cSRui Paulo {
3135b9c547cSRui Paulo 	struct macsec_qca_data *drv = priv;
3145b9c547cSRui Paulo 
31585732ac8SCy Schubert 	driver_wired_deinit_common(&drv->common);
3165b9c547cSRui Paulo 	os_free(drv);
3175b9c547cSRui Paulo }
3185b9c547cSRui Paulo 
3195b9c547cSRui Paulo 
macsec_qca_hapd_init(struct hostapd_data * hapd,struct wpa_init_params * params)320206b73d0SCy Schubert static void * macsec_qca_hapd_init(struct hostapd_data *hapd,
321206b73d0SCy Schubert 				   struct wpa_init_params *params)
322206b73d0SCy Schubert {
323206b73d0SCy Schubert 	struct macsec_qca_data *drv;
324206b73d0SCy Schubert 
325206b73d0SCy Schubert 	drv = os_zalloc(sizeof(struct macsec_qca_data));
326206b73d0SCy Schubert 	if (!drv) {
327206b73d0SCy Schubert 		wpa_printf(MSG_INFO,
328206b73d0SCy Schubert 			   "Could not allocate memory for macsec_qca driver data");
329206b73d0SCy Schubert 		return NULL;
330206b73d0SCy Schubert 	}
331206b73d0SCy Schubert 
3324b72b91aSCy Schubert 	if (macsec_qca_secy_id_get(params->ifname, &drv->secy_id)) {
3334b72b91aSCy Schubert 		wpa_printf(MSG_ERROR,
3344b72b91aSCy Schubert 			   "macsec_qca: Failed to get secy_id for %s",
3354b72b91aSCy Schubert 			   params->ifname);
3364b72b91aSCy Schubert 		os_free(drv);
3374b72b91aSCy Schubert 		return NULL;
3384b72b91aSCy Schubert 	}
339206b73d0SCy Schubert 
340206b73d0SCy Schubert 	drv->common.ctx = hapd;
341206b73d0SCy Schubert 	os_strlcpy(drv->common.ifname, params->ifname,
342206b73d0SCy Schubert 		   sizeof(drv->common.ifname));
343206b73d0SCy Schubert 	drv->use_pae_group_addr = params->use_pae_group_addr;
344206b73d0SCy Schubert 
345206b73d0SCy Schubert 	if (macsec_qca_init_sockets(drv, params->own_addr)) {
346206b73d0SCy Schubert 		os_free(drv);
347206b73d0SCy Schubert 		return NULL;
348206b73d0SCy Schubert 	}
349206b73d0SCy Schubert 
350206b73d0SCy Schubert 	return drv;
351206b73d0SCy Schubert }
352206b73d0SCy Schubert 
353206b73d0SCy Schubert 
macsec_qca_hapd_deinit(void * priv)354206b73d0SCy Schubert static void macsec_qca_hapd_deinit(void *priv)
355206b73d0SCy Schubert {
356206b73d0SCy Schubert 	struct macsec_qca_data *drv = priv;
357206b73d0SCy Schubert 
358206b73d0SCy Schubert 	if (drv->common.sock >= 0) {
359206b73d0SCy Schubert 		eloop_unregister_read_sock(drv->common.sock);
360206b73d0SCy Schubert 		close(drv->common.sock);
361206b73d0SCy Schubert 	}
362206b73d0SCy Schubert 
363206b73d0SCy Schubert 	os_free(drv);
364206b73d0SCy Schubert }
365206b73d0SCy Schubert 
366206b73d0SCy Schubert 
macsec_qca_send_eapol(void * priv,const u8 * addr,const u8 * data,size_t data_len,int encrypt,const u8 * own_addr,u32 flags,int link_id)367206b73d0SCy Schubert static int macsec_qca_send_eapol(void *priv, const u8 *addr,
368206b73d0SCy Schubert 				 const u8 *data, size_t data_len, int encrypt,
369*a90b9d01SCy Schubert 				 const u8 *own_addr, u32 flags, int link_id)
370206b73d0SCy Schubert {
371206b73d0SCy Schubert 	struct macsec_qca_data *drv = priv;
372206b73d0SCy Schubert 	struct ieee8023_hdr *hdr;
373206b73d0SCy Schubert 	size_t len;
374206b73d0SCy Schubert 	u8 *pos;
375206b73d0SCy Schubert 	int res;
376206b73d0SCy Schubert 
377206b73d0SCy Schubert 	len = sizeof(*hdr) + data_len;
378206b73d0SCy Schubert 	hdr = os_zalloc(len);
379206b73d0SCy Schubert 	if (!hdr) {
380206b73d0SCy Schubert 		wpa_printf(MSG_INFO,
381206b73d0SCy Schubert 			   "malloc() failed for macsec_qca_send_eapol(len=%lu)",
382206b73d0SCy Schubert 			   (unsigned long) len);
383206b73d0SCy Schubert 		return -1;
384206b73d0SCy Schubert 	}
385206b73d0SCy Schubert 
386206b73d0SCy Schubert 	os_memcpy(hdr->dest, drv->use_pae_group_addr ? pae_group_addr : addr,
387206b73d0SCy Schubert 		  ETH_ALEN);
388206b73d0SCy Schubert 	os_memcpy(hdr->src, own_addr, ETH_ALEN);
389206b73d0SCy Schubert 	hdr->ethertype = htons(ETH_P_PAE);
390206b73d0SCy Schubert 
391206b73d0SCy Schubert 	pos = (u8 *) (hdr + 1);
392206b73d0SCy Schubert 	os_memcpy(pos, data, data_len);
393206b73d0SCy Schubert 
394206b73d0SCy Schubert 	res = send(drv->common.sock, (u8 *) hdr, len, 0);
395206b73d0SCy Schubert 	os_free(hdr);
396206b73d0SCy Schubert 
397206b73d0SCy Schubert 	if (res < 0) {
398206b73d0SCy Schubert 		wpa_printf(MSG_ERROR,
399206b73d0SCy Schubert 			   "macsec_qca_send_eapol - packet len: %lu - failed: send: %s",
400206b73d0SCy Schubert 			   (unsigned long) len, strerror(errno));
401206b73d0SCy Schubert 	}
402206b73d0SCy Schubert 
403206b73d0SCy Schubert 	return res;
404206b73d0SCy Schubert }
405206b73d0SCy Schubert 
406206b73d0SCy Schubert 
macsec_qca_macsec_init(void * priv,struct macsec_init_params * params)4075b9c547cSRui Paulo static int macsec_qca_macsec_init(void *priv, struct macsec_init_params *params)
4085b9c547cSRui Paulo {
4095b9c547cSRui Paulo 	struct macsec_qca_data *drv = priv;
4105b9c547cSRui Paulo 
4115b9c547cSRui Paulo 	drv->always_include_sci = params->always_include_sci;
4125b9c547cSRui Paulo 	drv->use_es = params->use_es;
4135b9c547cSRui Paulo 	drv->use_scb = params->use_scb;
4145b9c547cSRui Paulo 
4155b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG, "%s: es=%d, scb=%d, sci=%d",
4165b9c547cSRui Paulo 		   __func__, drv->use_es, drv->use_scb,
4175b9c547cSRui Paulo 		   drv->always_include_sci);
4185b9c547cSRui Paulo 
4195b9c547cSRui Paulo 	__macsec_drv_init(drv);
4205b9c547cSRui Paulo 
4215b9c547cSRui Paulo 	return 0;
4225b9c547cSRui Paulo }
4235b9c547cSRui Paulo 
4245b9c547cSRui Paulo 
macsec_qca_macsec_deinit(void * priv)4255b9c547cSRui Paulo static int macsec_qca_macsec_deinit(void *priv)
4265b9c547cSRui Paulo {
4275b9c547cSRui Paulo 	struct macsec_qca_data *drv = priv;
4285b9c547cSRui Paulo 
4295b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG, "%s", __func__);
4305b9c547cSRui Paulo 
4315b9c547cSRui Paulo 	__macsec_drv_deinit(drv);
4325b9c547cSRui Paulo 
4335b9c547cSRui Paulo 	return 0;
4345b9c547cSRui Paulo }
4355b9c547cSRui Paulo 
4365b9c547cSRui Paulo 
macsec_qca_get_capability(void * priv,enum macsec_cap * cap)43785732ac8SCy Schubert static int macsec_qca_get_capability(void *priv, enum macsec_cap *cap)
43885732ac8SCy Schubert {
43985732ac8SCy Schubert 	wpa_printf(MSG_DEBUG, "%s", __func__);
44085732ac8SCy Schubert 
44185732ac8SCy Schubert 	*cap = MACSEC_CAP_INTEG_AND_CONF_0_30_50;
44285732ac8SCy Schubert 
44385732ac8SCy Schubert 	return 0;
44485732ac8SCy Schubert }
44585732ac8SCy Schubert 
44685732ac8SCy Schubert 
macsec_qca_enable_protect_frames(void * priv,bool enabled)447c1d255d3SCy Schubert static int macsec_qca_enable_protect_frames(void *priv, bool enabled)
4485b9c547cSRui Paulo {
4495b9c547cSRui Paulo 	struct macsec_qca_data *drv = priv;
4505b9c547cSRui Paulo 	int ret = 0;
4515b9c547cSRui Paulo 
4525b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
4535b9c547cSRui Paulo 
4545b9c547cSRui Paulo 	drv->protect_frames = enabled;
4555b9c547cSRui Paulo 
4565b9c547cSRui Paulo 	return ret;
4575b9c547cSRui Paulo }
4585b9c547cSRui Paulo 
4595b9c547cSRui Paulo 
macsec_qca_set_replay_protect(void * priv,bool enabled,unsigned int window)460c1d255d3SCy Schubert static int macsec_qca_set_replay_protect(void *priv, bool enabled,
4615b9c547cSRui Paulo 					 unsigned int window)
4625b9c547cSRui Paulo {
4635b9c547cSRui Paulo 	struct macsec_qca_data *drv = priv;
4645b9c547cSRui Paulo 	int ret = 0;
4655b9c547cSRui Paulo 
4665b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG, "%s: enabled=%d, win=%u",
4675b9c547cSRui Paulo 		   __func__, enabled, window);
4685b9c547cSRui Paulo 
4695b9c547cSRui Paulo 	drv->replay_protect = enabled;
4705b9c547cSRui Paulo 	drv->replay_window = window;
4715b9c547cSRui Paulo 
4725b9c547cSRui Paulo 	return ret;
4735b9c547cSRui Paulo }
4745b9c547cSRui Paulo 
4755b9c547cSRui Paulo 
macsec_qca_cs_type_get(u64 cs)47685732ac8SCy Schubert static fal_cipher_suite_e macsec_qca_cs_type_get(u64 cs)
47785732ac8SCy Schubert {
47885732ac8SCy Schubert 	if (cs == CS_ID_GCM_AES_128)
47985732ac8SCy Schubert 		return FAL_CIPHER_SUITE_AES_GCM_128;
48085732ac8SCy Schubert 	if (cs == CS_ID_GCM_AES_256)
48185732ac8SCy Schubert 		return FAL_CIPHER_SUITE_AES_GCM_256;
48285732ac8SCy Schubert 	return FAL_CIPHER_SUITE_MAX;
48385732ac8SCy Schubert }
48485732ac8SCy Schubert 
48585732ac8SCy Schubert 
macsec_qca_set_current_cipher_suite(void * priv,u64 cs)486780fb4a2SCy Schubert static int macsec_qca_set_current_cipher_suite(void *priv, u64 cs)
4875b9c547cSRui Paulo {
48885732ac8SCy Schubert 	struct macsec_qca_data *drv = priv;
48985732ac8SCy Schubert 	fal_cipher_suite_e cs_type;
49085732ac8SCy Schubert 
49185732ac8SCy Schubert 	if (cs != CS_ID_GCM_AES_128 && cs != CS_ID_GCM_AES_256) {
492780fb4a2SCy Schubert 		wpa_printf(MSG_ERROR,
493780fb4a2SCy Schubert 			   "%s: NOT supported CipherSuite: %016" PRIx64,
494780fb4a2SCy Schubert 			   __func__, cs);
4955b9c547cSRui Paulo 		return -1;
4965b9c547cSRui Paulo 	}
4975b9c547cSRui Paulo 
49885732ac8SCy Schubert 	wpa_printf(MSG_DEBUG, "%s: CipherSuite: %016" PRIx64, __func__, cs);
4995b9c547cSRui Paulo 
50085732ac8SCy Schubert 	cs_type = macsec_qca_cs_type_get(cs);
50185732ac8SCy Schubert 	return nss_macsec_secy_cipher_suite_set(drv->secy_id, cs_type);
5025b9c547cSRui Paulo }
5035b9c547cSRui Paulo 
5045b9c547cSRui Paulo 
macsec_qca_enable_controlled_port(void * priv,bool enabled)505c1d255d3SCy Schubert static int macsec_qca_enable_controlled_port(void *priv, bool enabled)
5065b9c547cSRui Paulo {
5075b9c547cSRui Paulo 	struct macsec_qca_data *drv = priv;
5085b9c547cSRui Paulo 	int ret = 0;
5095b9c547cSRui Paulo 
5105b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG, "%s: enable=%d", __func__, enabled);
5115b9c547cSRui Paulo 
5125b9c547cSRui Paulo 	ret += nss_macsec_secy_controlled_port_en_set(drv->secy_id, enabled);
5135b9c547cSRui Paulo 
5145b9c547cSRui Paulo 	return ret;
5155b9c547cSRui Paulo }
5165b9c547cSRui Paulo 
5175b9c547cSRui Paulo 
macsec_qca_lookup_channel(struct channel_map * map,struct ieee802_1x_mka_sci * sci,u32 * channel)51885732ac8SCy Schubert static int macsec_qca_lookup_channel(struct channel_map *map,
51985732ac8SCy Schubert 				     struct ieee802_1x_mka_sci *sci,
52085732ac8SCy Schubert 				     u32 *channel)
52185732ac8SCy Schubert {
52285732ac8SCy Schubert 	u32 i;
52385732ac8SCy Schubert 
52485732ac8SCy Schubert 	for (i = 0; i < MAXSC; i++) {
52585732ac8SCy Schubert 		if (os_memcmp(&map[i].sci, sci,
52685732ac8SCy Schubert 			      sizeof(struct ieee802_1x_mka_sci)) == 0) {
52785732ac8SCy Schubert 			*channel = i;
52885732ac8SCy Schubert 			return 0;
52985732ac8SCy Schubert 		}
53085732ac8SCy Schubert 	}
53185732ac8SCy Schubert 
53285732ac8SCy Schubert 	return -1;
53385732ac8SCy Schubert }
53485732ac8SCy Schubert 
53585732ac8SCy Schubert 
macsec_qca_register_channel(struct channel_map * map,struct ieee802_1x_mka_sci * sci,u32 channel)53685732ac8SCy Schubert static void macsec_qca_register_channel(struct channel_map *map,
53785732ac8SCy Schubert 					struct ieee802_1x_mka_sci *sci,
53885732ac8SCy Schubert 					u32 channel)
53985732ac8SCy Schubert {
54085732ac8SCy Schubert 	os_memcpy(&map[channel].sci, sci, sizeof(struct ieee802_1x_mka_sci));
54185732ac8SCy Schubert }
54285732ac8SCy Schubert 
54385732ac8SCy Schubert 
macsec_qca_lookup_receive_channel(struct macsec_qca_data * drv,struct receive_sc * sc,u32 * channel)54485732ac8SCy Schubert static int macsec_qca_lookup_receive_channel(struct macsec_qca_data *drv,
54585732ac8SCy Schubert 					     struct receive_sc *sc,
54685732ac8SCy Schubert 					     u32 *channel)
54785732ac8SCy Schubert {
54885732ac8SCy Schubert 	return macsec_qca_lookup_channel(drv->receive_channel_map, &sc->sci,
54985732ac8SCy Schubert 					 channel);
55085732ac8SCy Schubert }
55185732ac8SCy Schubert 
55285732ac8SCy Schubert 
macsec_qca_register_receive_channel(struct macsec_qca_data * drv,struct receive_sc * sc,u32 channel)55385732ac8SCy Schubert static void macsec_qca_register_receive_channel(struct macsec_qca_data *drv,
55485732ac8SCy Schubert 						struct receive_sc *sc,
55585732ac8SCy Schubert 						u32 channel)
55685732ac8SCy Schubert {
55785732ac8SCy Schubert 	macsec_qca_register_channel(drv->receive_channel_map, &sc->sci,
55885732ac8SCy Schubert 				    channel);
55985732ac8SCy Schubert }
56085732ac8SCy Schubert 
56185732ac8SCy Schubert 
macsec_qca_lookup_transmit_channel(struct macsec_qca_data * drv,struct transmit_sc * sc,u32 * channel)56285732ac8SCy Schubert static int macsec_qca_lookup_transmit_channel(struct macsec_qca_data *drv,
56385732ac8SCy Schubert 					      struct transmit_sc *sc,
56485732ac8SCy Schubert 					      u32 *channel)
56585732ac8SCy Schubert {
56685732ac8SCy Schubert 	return macsec_qca_lookup_channel(drv->transmit_channel_map, &sc->sci,
56785732ac8SCy Schubert 					 channel);
56885732ac8SCy Schubert }
56985732ac8SCy Schubert 
57085732ac8SCy Schubert 
macsec_qca_register_transmit_channel(struct macsec_qca_data * drv,struct transmit_sc * sc,u32 channel)57185732ac8SCy Schubert static void macsec_qca_register_transmit_channel(struct macsec_qca_data *drv,
57285732ac8SCy Schubert 						 struct transmit_sc *sc,
57385732ac8SCy Schubert 						 u32 channel)
57485732ac8SCy Schubert {
57585732ac8SCy Schubert 	macsec_qca_register_channel(drv->transmit_channel_map, &sc->sci,
57685732ac8SCy Schubert 				    channel);
57785732ac8SCy Schubert }
57885732ac8SCy Schubert 
57985732ac8SCy Schubert 
macsec_qca_get_receive_lowest_pn(void * priv,struct receive_sa * sa)58085732ac8SCy Schubert static int macsec_qca_get_receive_lowest_pn(void *priv, struct receive_sa *sa)
5815b9c547cSRui Paulo {
5825b9c547cSRui Paulo 	struct macsec_qca_data *drv = priv;
5835b9c547cSRui Paulo 	int ret = 0;
5845b9c547cSRui Paulo 	u32 next_pn = 0;
585c1d255d3SCy Schubert 	bool enabled = false;
5865b9c547cSRui Paulo 	u32 win;
58785732ac8SCy Schubert 	u32 channel;
5885b9c547cSRui Paulo 
58985732ac8SCy Schubert 	ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel);
59085732ac8SCy Schubert 	if (ret != 0)
59185732ac8SCy Schubert 		return ret;
59285732ac8SCy Schubert 
59385732ac8SCy Schubert 	ret += nss_macsec_secy_rx_sa_next_pn_get(drv->secy_id, channel, sa->an,
5945b9c547cSRui Paulo 						 &next_pn);
5955b9c547cSRui Paulo 	ret += nss_macsec_secy_rx_sc_replay_protect_get(drv->secy_id, channel,
5965b9c547cSRui Paulo 							&enabled);
5975b9c547cSRui Paulo 	ret += nss_macsec_secy_rx_sc_anti_replay_window_get(drv->secy_id,
5985b9c547cSRui Paulo 							    channel, &win);
5995b9c547cSRui Paulo 
6005b9c547cSRui Paulo 	if (enabled)
60185732ac8SCy Schubert 		sa->lowest_pn = (next_pn > win) ? (next_pn - win) : 1;
6025b9c547cSRui Paulo 	else
60385732ac8SCy Schubert 		sa->lowest_pn = next_pn;
6045b9c547cSRui Paulo 
60585732ac8SCy Schubert 	wpa_printf(MSG_DEBUG, "%s: lpn=0x%x", __func__, sa->lowest_pn);
6065b9c547cSRui Paulo 
6075b9c547cSRui Paulo 	return ret;
6085b9c547cSRui Paulo }
6095b9c547cSRui Paulo 
6105b9c547cSRui Paulo 
macsec_qca_get_transmit_next_pn(void * priv,struct transmit_sa * sa)61185732ac8SCy Schubert static int macsec_qca_get_transmit_next_pn(void *priv, struct transmit_sa *sa)
6125b9c547cSRui Paulo {
6135b9c547cSRui Paulo 	struct macsec_qca_data *drv = priv;
6145b9c547cSRui Paulo 	int ret = 0;
61585732ac8SCy Schubert 	u32 channel;
6165b9c547cSRui Paulo 
61785732ac8SCy Schubert 	ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel);
61885732ac8SCy Schubert 	if (ret != 0)
61985732ac8SCy Schubert 		return ret;
6205b9c547cSRui Paulo 
62185732ac8SCy Schubert 	ret += nss_macsec_secy_tx_sa_next_pn_get(drv->secy_id, channel, sa->an,
62285732ac8SCy Schubert 						 &sa->next_pn);
62385732ac8SCy Schubert 
62485732ac8SCy Schubert 	wpa_printf(MSG_DEBUG, "%s: npn=0x%x", __func__, sa->next_pn);
6255b9c547cSRui Paulo 
6265b9c547cSRui Paulo 	return ret;
6275b9c547cSRui Paulo }
6285b9c547cSRui Paulo 
6295b9c547cSRui Paulo 
macsec_qca_set_transmit_next_pn(void * priv,struct transmit_sa * sa)63085732ac8SCy Schubert static int macsec_qca_set_transmit_next_pn(void *priv, struct transmit_sa *sa)
6315b9c547cSRui Paulo {
6325b9c547cSRui Paulo 	struct macsec_qca_data *drv = priv;
6335b9c547cSRui Paulo 	int ret = 0;
63485732ac8SCy Schubert 	u32 channel;
6355b9c547cSRui Paulo 
63685732ac8SCy Schubert 	ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel);
63785732ac8SCy Schubert 	if (ret != 0)
63885732ac8SCy Schubert 		return ret;
6395b9c547cSRui Paulo 
64085732ac8SCy Schubert 	ret += nss_macsec_secy_tx_sa_next_pn_set(drv->secy_id, channel, sa->an,
64185732ac8SCy Schubert 						 sa->next_pn);
64285732ac8SCy Schubert 
64385732ac8SCy Schubert 	wpa_printf(MSG_INFO, "%s: npn=0x%x", __func__, sa->next_pn);
6445b9c547cSRui Paulo 
6455b9c547cSRui Paulo 	return ret;
6465b9c547cSRui Paulo }
6475b9c547cSRui Paulo 
6485b9c547cSRui Paulo 
macsec_qca_get_available_receive_sc(void * priv,u32 * channel)6495b9c547cSRui Paulo static int macsec_qca_get_available_receive_sc(void *priv, u32 *channel)
6505b9c547cSRui Paulo {
6515b9c547cSRui Paulo 	struct macsec_qca_data *drv = priv;
6525b9c547cSRui Paulo 	int ret = 0;
6535b9c547cSRui Paulo 	u32 sc_ch = 0;
654c1d255d3SCy Schubert 	bool in_use = false;
6555b9c547cSRui Paulo 
6565b9c547cSRui Paulo 	for (sc_ch = 0; sc_ch < MAXSC; sc_ch++) {
6575b9c547cSRui Paulo 		ret = nss_macsec_secy_rx_sc_in_used_get(drv->secy_id, sc_ch,
6585b9c547cSRui Paulo 							&in_use);
6595b9c547cSRui Paulo 		if (ret)
6605b9c547cSRui Paulo 			continue;
6615b9c547cSRui Paulo 
6625b9c547cSRui Paulo 		if (!in_use) {
6635b9c547cSRui Paulo 			*channel = sc_ch;
6645b9c547cSRui Paulo 			wpa_printf(MSG_DEBUG, "%s: channel=%d",
6655b9c547cSRui Paulo 				   __func__, *channel);
6665b9c547cSRui Paulo 			return 0;
6675b9c547cSRui Paulo 		}
6685b9c547cSRui Paulo 	}
6695b9c547cSRui Paulo 
6705b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG, "%s: no available channel", __func__);
6715b9c547cSRui Paulo 
6725b9c547cSRui Paulo 	return -1;
6735b9c547cSRui Paulo }
6745b9c547cSRui Paulo 
6755b9c547cSRui Paulo 
macsec_qca_create_receive_sc(void * priv,struct receive_sc * sc,unsigned int conf_offset,int validation)67685732ac8SCy Schubert static int macsec_qca_create_receive_sc(void *priv, struct receive_sc *sc,
6775b9c547cSRui Paulo 					unsigned int conf_offset,
6785b9c547cSRui Paulo 					int validation)
6795b9c547cSRui Paulo {
6805b9c547cSRui Paulo 	struct macsec_qca_data *drv = priv;
6815b9c547cSRui Paulo 	int ret = 0;
6825b9c547cSRui Paulo 	fal_rx_prc_lut_t entry;
6835b9c547cSRui Paulo 	fal_rx_sc_validate_frame_e vf;
6845b9c547cSRui Paulo 	enum validate_frames validate_frames = validation;
68585732ac8SCy Schubert 	u32 channel;
68685732ac8SCy Schubert 	const u8 *sci_addr = sc->sci.addr;
68785732ac8SCy Schubert 	u16 sci_port = be_to_host16(sc->sci.port);
68885732ac8SCy Schubert 
68985732ac8SCy Schubert 	ret = macsec_qca_get_available_receive_sc(priv, &channel);
69085732ac8SCy Schubert 	if (ret != 0)
69185732ac8SCy Schubert 		return ret;
6925b9c547cSRui Paulo 
6935b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel);
6945b9c547cSRui Paulo 
6955b9c547cSRui Paulo 	/* rx prc lut */
6965b9c547cSRui Paulo 	os_memset(&entry, 0, sizeof(entry));
6975b9c547cSRui Paulo 
6985b9c547cSRui Paulo 	os_memcpy(entry.sci, sci_addr, ETH_ALEN);
69985732ac8SCy Schubert 	entry.sci[6] = (sci_port >> 8) & 0xff;
70085732ac8SCy Schubert 	entry.sci[7] = sci_port & 0xff;
7015b9c547cSRui Paulo 	entry.sci_mask = 0xf;
7025b9c547cSRui Paulo 
7035b9c547cSRui Paulo 	entry.valid = 1;
7045b9c547cSRui Paulo 	entry.channel = channel;
7055b9c547cSRui Paulo 	entry.action = FAL_RX_PRC_ACTION_PROCESS;
7065b9c547cSRui Paulo 	entry.offset = conf_offset;
7075b9c547cSRui Paulo 
7085b9c547cSRui Paulo 	/* rx validate frame  */
7095b9c547cSRui Paulo 	if (validate_frames == Strict)
7105b9c547cSRui Paulo 		vf = FAL_RX_SC_VALIDATE_FRAME_STRICT;
7115b9c547cSRui Paulo 	else if (validate_frames == Checked)
7125b9c547cSRui Paulo 		vf = FAL_RX_SC_VALIDATE_FRAME_CHECK;
7135b9c547cSRui Paulo 	else
7145b9c547cSRui Paulo 		vf = FAL_RX_SC_VALIDATE_FRAME_DISABLED;
7155b9c547cSRui Paulo 
7165b9c547cSRui Paulo 	ret += nss_macsec_secy_rx_prc_lut_set(drv->secy_id, channel, &entry);
7175b9c547cSRui Paulo 	ret += nss_macsec_secy_rx_sc_create(drv->secy_id, channel);
7185b9c547cSRui Paulo 	ret += nss_macsec_secy_rx_sc_validate_frame_set(drv->secy_id, channel,
7195b9c547cSRui Paulo 							vf);
7205b9c547cSRui Paulo 	ret += nss_macsec_secy_rx_sc_replay_protect_set(drv->secy_id, channel,
7215b9c547cSRui Paulo 							drv->replay_protect);
7225b9c547cSRui Paulo 	ret += nss_macsec_secy_rx_sc_anti_replay_window_set(drv->secy_id,
7235b9c547cSRui Paulo 							    channel,
7245b9c547cSRui Paulo 							    drv->replay_window);
7255b9c547cSRui Paulo 
72685732ac8SCy Schubert 	macsec_qca_register_receive_channel(drv, sc, channel);
72785732ac8SCy Schubert 
7285b9c547cSRui Paulo 	return ret;
7295b9c547cSRui Paulo }
7305b9c547cSRui Paulo 
7315b9c547cSRui Paulo 
macsec_qca_delete_receive_sc(void * priv,struct receive_sc * sc)73285732ac8SCy Schubert static int macsec_qca_delete_receive_sc(void *priv, struct receive_sc *sc)
7335b9c547cSRui Paulo {
7345b9c547cSRui Paulo 	struct macsec_qca_data *drv = priv;
73585732ac8SCy Schubert 	int ret;
7365b9c547cSRui Paulo 	fal_rx_prc_lut_t entry;
73785732ac8SCy Schubert 	u32 channel;
73885732ac8SCy Schubert 
73985732ac8SCy Schubert 	ret = macsec_qca_lookup_receive_channel(priv, sc, &channel);
74085732ac8SCy Schubert 	if (ret != 0)
74185732ac8SCy Schubert 		return ret;
7425b9c547cSRui Paulo 
7435b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel);
7445b9c547cSRui Paulo 
7455b9c547cSRui Paulo 	/* rx prc lut */
7465b9c547cSRui Paulo 	os_memset(&entry, 0, sizeof(entry));
7475b9c547cSRui Paulo 
7485b9c547cSRui Paulo 	ret += nss_macsec_secy_rx_sc_del(drv->secy_id, channel);
7495b9c547cSRui Paulo 	ret += nss_macsec_secy_rx_prc_lut_set(drv->secy_id, channel, &entry);
7505b9c547cSRui Paulo 
7515b9c547cSRui Paulo 	return ret;
7525b9c547cSRui Paulo }
7535b9c547cSRui Paulo 
7545b9c547cSRui Paulo 
macsec_qca_create_receive_sa(void * priv,struct receive_sa * sa)75585732ac8SCy Schubert static int macsec_qca_create_receive_sa(void *priv, struct receive_sa *sa)
7565b9c547cSRui Paulo {
7575b9c547cSRui Paulo 	struct macsec_qca_data *drv = priv;
75885732ac8SCy Schubert 	int ret;
7595b9c547cSRui Paulo 	fal_rx_sak_t rx_sak;
7605b9c547cSRui Paulo 	int i = 0;
76185732ac8SCy Schubert 	u32 channel;
76285732ac8SCy Schubert 	fal_rx_prc_lut_t entry;
76385732ac8SCy Schubert 	u32 offset;
76485732ac8SCy Schubert 
76585732ac8SCy Schubert 	ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel);
76685732ac8SCy Schubert 	if (ret != 0)
76785732ac8SCy Schubert 		return ret;
7685b9c547cSRui Paulo 
7695b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG, "%s, channel=%d, an=%d, lpn=0x%x",
77085732ac8SCy Schubert 		   __func__, channel, sa->an, sa->lowest_pn);
7715b9c547cSRui Paulo 
7725b9c547cSRui Paulo 	os_memset(&rx_sak, 0, sizeof(rx_sak));
77385732ac8SCy Schubert 	rx_sak.sak_len = sa->pkey->key_len;
77485732ac8SCy Schubert 	if (sa->pkey->key_len == SAK_128_LEN) {
7755b9c547cSRui Paulo 		for (i = 0; i < 16; i++)
77685732ac8SCy Schubert 			rx_sak.sak[i] = sa->pkey->key[15 - i];
77785732ac8SCy Schubert 	} else if (sa->pkey->key_len == SAK_256_LEN) {
77885732ac8SCy Schubert 		for (i = 0; i < 16; i++) {
77985732ac8SCy Schubert 			rx_sak.sak1[i] = sa->pkey->key[15 - i];
78085732ac8SCy Schubert 			rx_sak.sak[i] = sa->pkey->key[31 - i];
78185732ac8SCy Schubert 		}
78285732ac8SCy Schubert 	} else {
78385732ac8SCy Schubert 		return -1;
78485732ac8SCy Schubert 	}
7855b9c547cSRui Paulo 
78685732ac8SCy Schubert 	if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_0)
78785732ac8SCy Schubert 		offset = 0;
78885732ac8SCy Schubert 	else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_30)
78985732ac8SCy Schubert 		offset = 30;
79085732ac8SCy Schubert 	else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_50)
79185732ac8SCy Schubert 		offset = 50;
79285732ac8SCy Schubert 	else
79385732ac8SCy Schubert 		return -1;
79485732ac8SCy Schubert 	ret += nss_macsec_secy_rx_prc_lut_get(drv->secy_id, channel, &entry);
79585732ac8SCy Schubert 	entry.offset = offset;
79685732ac8SCy Schubert 	ret += nss_macsec_secy_rx_prc_lut_set(drv->secy_id, channel, &entry);
79785732ac8SCy Schubert 	ret += nss_macsec_secy_rx_sa_create(drv->secy_id, channel, sa->an);
79885732ac8SCy Schubert 	ret += nss_macsec_secy_rx_sak_set(drv->secy_id, channel, sa->an,
79985732ac8SCy Schubert 					  &rx_sak);
8005b9c547cSRui Paulo 
8015b9c547cSRui Paulo 	return ret;
8025b9c547cSRui Paulo }
8035b9c547cSRui Paulo 
8045b9c547cSRui Paulo 
macsec_qca_enable_receive_sa(void * priv,struct receive_sa * sa)80585732ac8SCy Schubert static int macsec_qca_enable_receive_sa(void *priv, struct receive_sa *sa)
8065b9c547cSRui Paulo {
8075b9c547cSRui Paulo 	struct macsec_qca_data *drv = priv;
80885732ac8SCy Schubert 	int ret;
80985732ac8SCy Schubert 	u32 channel;
8105b9c547cSRui Paulo 
81185732ac8SCy Schubert 	ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel);
81285732ac8SCy Schubert 	if (ret != 0)
81385732ac8SCy Schubert 		return ret;
8145b9c547cSRui Paulo 
81585732ac8SCy Schubert 	wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel,
81685732ac8SCy Schubert 		   sa->an);
81785732ac8SCy Schubert 
81885732ac8SCy Schubert 	ret += nss_macsec_secy_rx_sa_en_set(drv->secy_id, channel, sa->an,
819c1d255d3SCy Schubert 					    true);
8205b9c547cSRui Paulo 
8215b9c547cSRui Paulo 	return ret;
8225b9c547cSRui Paulo }
8235b9c547cSRui Paulo 
8245b9c547cSRui Paulo 
macsec_qca_disable_receive_sa(void * priv,struct receive_sa * sa)82585732ac8SCy Schubert static int macsec_qca_disable_receive_sa(void *priv, struct receive_sa *sa)
8265b9c547cSRui Paulo {
8275b9c547cSRui Paulo 	struct macsec_qca_data *drv = priv;
82885732ac8SCy Schubert 	int ret;
82985732ac8SCy Schubert 	u32 channel;
8305b9c547cSRui Paulo 
83185732ac8SCy Schubert 	ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel);
83285732ac8SCy Schubert 	if (ret != 0)
83385732ac8SCy Schubert 		return ret;
8345b9c547cSRui Paulo 
83585732ac8SCy Schubert 	wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel,
83685732ac8SCy Schubert 		   sa->an);
83785732ac8SCy Schubert 
83885732ac8SCy Schubert 	ret += nss_macsec_secy_rx_sa_en_set(drv->secy_id, channel, sa->an,
839c1d255d3SCy Schubert 					    false);
8405b9c547cSRui Paulo 
8415b9c547cSRui Paulo 	return ret;
8425b9c547cSRui Paulo }
8435b9c547cSRui Paulo 
8445b9c547cSRui Paulo 
macsec_qca_get_available_transmit_sc(void * priv,u32 * channel)8455b9c547cSRui Paulo static int macsec_qca_get_available_transmit_sc(void *priv, u32 *channel)
8465b9c547cSRui Paulo {
8475b9c547cSRui Paulo 	struct macsec_qca_data *drv = priv;
8485b9c547cSRui Paulo 	u32 sc_ch = 0;
849c1d255d3SCy Schubert 	bool in_use = false;
8505b9c547cSRui Paulo 
8515b9c547cSRui Paulo 	for (sc_ch = 0; sc_ch < MAXSC; sc_ch++) {
85285732ac8SCy Schubert 		if (nss_macsec_secy_tx_sc_in_used_get(drv->secy_id, sc_ch,
85385732ac8SCy Schubert 						      &in_use))
8545b9c547cSRui Paulo 			continue;
8555b9c547cSRui Paulo 
8565b9c547cSRui Paulo 		if (!in_use) {
8575b9c547cSRui Paulo 			*channel = sc_ch;
8585b9c547cSRui Paulo 			wpa_printf(MSG_DEBUG, "%s: channel=%d",
8595b9c547cSRui Paulo 				   __func__, *channel);
8605b9c547cSRui Paulo 			return 0;
8615b9c547cSRui Paulo 		}
8625b9c547cSRui Paulo 	}
8635b9c547cSRui Paulo 
864*a90b9d01SCy Schubert 	wpa_printf(MSG_DEBUG, "%s: no available channel", __func__);
8655b9c547cSRui Paulo 
8665b9c547cSRui Paulo 	return -1;
8675b9c547cSRui Paulo }
8685b9c547cSRui Paulo 
8695b9c547cSRui Paulo 
macsec_qca_create_transmit_sc(void * priv,struct transmit_sc * sc,unsigned int conf_offset)87085732ac8SCy Schubert static int macsec_qca_create_transmit_sc(void *priv, struct transmit_sc *sc,
8715b9c547cSRui Paulo 					 unsigned int conf_offset)
8725b9c547cSRui Paulo {
8735b9c547cSRui Paulo 	struct macsec_qca_data *drv = priv;
87485732ac8SCy Schubert 	int ret;
8755b9c547cSRui Paulo 	fal_tx_class_lut_t entry;
8765b9c547cSRui Paulo 	u8 psci[ETH_ALEN + 2];
87785732ac8SCy Schubert 	u32 channel;
87885732ac8SCy Schubert 	u16 sci_port = be_to_host16(sc->sci.port);
87985732ac8SCy Schubert 
88085732ac8SCy Schubert 	ret = macsec_qca_get_available_transmit_sc(priv, &channel);
88185732ac8SCy Schubert 	if (ret != 0)
88285732ac8SCy Schubert 		return ret;
8835b9c547cSRui Paulo 
8845b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel);
8855b9c547cSRui Paulo 
8865b9c547cSRui Paulo 	/* class lut */
8875b9c547cSRui Paulo 	os_memset(&entry, 0, sizeof(entry));
8885b9c547cSRui Paulo 
8895b9c547cSRui Paulo 	entry.valid = 1;
8905b9c547cSRui Paulo 	entry.action = FAL_TX_CLASS_ACTION_FORWARD;
8915b9c547cSRui Paulo 	entry.channel = channel;
8925b9c547cSRui Paulo 
89385732ac8SCy Schubert 	os_memcpy(psci, sc->sci.addr, ETH_ALEN);
89485732ac8SCy Schubert 	psci[6] = (sci_port >> 8) & 0xff;
89585732ac8SCy Schubert 	psci[7] = sci_port & 0xff;
8965b9c547cSRui Paulo 
8975b9c547cSRui Paulo 	ret += nss_macsec_secy_tx_class_lut_set(drv->secy_id, channel, &entry);
8985b9c547cSRui Paulo 	ret += nss_macsec_secy_tx_sc_create(drv->secy_id, channel, psci, 8);
8995b9c547cSRui Paulo 	ret += nss_macsec_secy_tx_sc_protect_set(drv->secy_id, channel,
9005b9c547cSRui Paulo 						 drv->protect_frames);
9015b9c547cSRui Paulo 	ret += nss_macsec_secy_tx_sc_confidentiality_offset_set(drv->secy_id,
9025b9c547cSRui Paulo 								channel,
9035b9c547cSRui Paulo 								conf_offset);
9045b9c547cSRui Paulo 
90585732ac8SCy Schubert 	macsec_qca_register_transmit_channel(drv, sc, channel);
90685732ac8SCy Schubert 
9075b9c547cSRui Paulo 	return ret;
9085b9c547cSRui Paulo }
9095b9c547cSRui Paulo 
9105b9c547cSRui Paulo 
macsec_qca_delete_transmit_sc(void * priv,struct transmit_sc * sc)91185732ac8SCy Schubert static int macsec_qca_delete_transmit_sc(void *priv, struct transmit_sc *sc)
9125b9c547cSRui Paulo {
9135b9c547cSRui Paulo 	struct macsec_qca_data *drv = priv;
91485732ac8SCy Schubert 	int ret;
9155b9c547cSRui Paulo 	fal_tx_class_lut_t entry;
91685732ac8SCy Schubert 	u32 channel;
91785732ac8SCy Schubert 
91885732ac8SCy Schubert 	ret = macsec_qca_lookup_transmit_channel(priv, sc, &channel);
91985732ac8SCy Schubert 	if (ret != 0)
92085732ac8SCy Schubert 		return ret;
9215b9c547cSRui Paulo 
9225b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel);
9235b9c547cSRui Paulo 
9245b9c547cSRui Paulo 	/* class lut */
9255b9c547cSRui Paulo 	os_memset(&entry, 0, sizeof(entry));
9265b9c547cSRui Paulo 
9275b9c547cSRui Paulo 	ret += nss_macsec_secy_tx_class_lut_set(drv->secy_id, channel, &entry);
9285b9c547cSRui Paulo 	ret += nss_macsec_secy_tx_sc_del(drv->secy_id, channel);
9295b9c547cSRui Paulo 
9305b9c547cSRui Paulo 	return ret;
9315b9c547cSRui Paulo }
9325b9c547cSRui Paulo 
9335b9c547cSRui Paulo 
macsec_qca_create_transmit_sa(void * priv,struct transmit_sa * sa)93485732ac8SCy Schubert static int macsec_qca_create_transmit_sa(void *priv, struct transmit_sa *sa)
9355b9c547cSRui Paulo {
9365b9c547cSRui Paulo 	struct macsec_qca_data *drv = priv;
93785732ac8SCy Schubert 	int ret;
9385b9c547cSRui Paulo 	u8 tci = 0;
9395b9c547cSRui Paulo 	fal_tx_sak_t tx_sak;
9405b9c547cSRui Paulo 	int i;
94185732ac8SCy Schubert 	u32 channel;
94285732ac8SCy Schubert 	u32 offset;
94385732ac8SCy Schubert 
94485732ac8SCy Schubert 	ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel);
94585732ac8SCy Schubert 	if (ret != 0)
94685732ac8SCy Schubert 		return ret;
9475b9c547cSRui Paulo 
9485b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG,
9495b9c547cSRui Paulo 		   "%s: channel=%d, an=%d, next_pn=0x%x, confidentiality=%d",
95085732ac8SCy Schubert 		   __func__, channel, sa->an, sa->next_pn, sa->confidentiality);
9515b9c547cSRui Paulo 
9525b9c547cSRui Paulo 	if (drv->always_include_sci)
9535b9c547cSRui Paulo 		tci |= TCI_SC;
9545b9c547cSRui Paulo 	else if (drv->use_es)
9555b9c547cSRui Paulo 		tci |= TCI_ES;
9565b9c547cSRui Paulo 	else if (drv->use_scb)
9575b9c547cSRui Paulo 		tci |= TCI_SCB;
9585b9c547cSRui Paulo 
95985732ac8SCy Schubert 	if (sa->confidentiality)
9605b9c547cSRui Paulo 		tci |= TCI_E | TCI_C;
9615b9c547cSRui Paulo 
9625b9c547cSRui Paulo 	os_memset(&tx_sak, 0, sizeof(tx_sak));
96385732ac8SCy Schubert 	tx_sak.sak_len = sa->pkey->key_len;
96485732ac8SCy Schubert 	if (sa->pkey->key_len == SAK_128_LEN) {
9655b9c547cSRui Paulo 		for (i = 0; i < 16; i++)
96685732ac8SCy Schubert 			tx_sak.sak[i] = sa->pkey->key[15 - i];
96785732ac8SCy Schubert 	} else if (sa->pkey->key_len == SAK_256_LEN) {
96885732ac8SCy Schubert 		for (i = 0; i < 16; i++) {
96985732ac8SCy Schubert 			tx_sak.sak1[i] = sa->pkey->key[15 - i];
97085732ac8SCy Schubert 			tx_sak.sak[i] = sa->pkey->key[31 - i];
97185732ac8SCy Schubert 		}
97285732ac8SCy Schubert 	} else {
97385732ac8SCy Schubert 		return -1;
97485732ac8SCy Schubert 	}
9755b9c547cSRui Paulo 
97685732ac8SCy Schubert 	if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_0)
97785732ac8SCy Schubert 		offset = 0;
97885732ac8SCy Schubert 	else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_30)
97985732ac8SCy Schubert 		offset = 30;
98085732ac8SCy Schubert 	else if (sa->pkey->confidentiality_offset == CONFIDENTIALITY_OFFSET_50)
98185732ac8SCy Schubert 		offset = 50;
98285732ac8SCy Schubert 	else
98385732ac8SCy Schubert 		return -1;
98485732ac8SCy Schubert 	ret += nss_macsec_secy_tx_sc_confidentiality_offset_set(drv->secy_id,
98585732ac8SCy Schubert 								channel,
98685732ac8SCy Schubert 								offset);
98785732ac8SCy Schubert 	ret += nss_macsec_secy_tx_sa_next_pn_set(drv->secy_id, channel, sa->an,
98885732ac8SCy Schubert 						 sa->next_pn);
98985732ac8SCy Schubert 	ret += nss_macsec_secy_tx_sak_set(drv->secy_id, channel, sa->an,
99085732ac8SCy Schubert 					  &tx_sak);
9915b9c547cSRui Paulo 	ret += nss_macsec_secy_tx_sc_tci_7_2_set(drv->secy_id, channel,
9925b9c547cSRui Paulo 						 (tci >> 2));
99385732ac8SCy Schubert 	ret += nss_macsec_secy_tx_sc_an_set(drv->secy_id, channel, sa->an);
9945b9c547cSRui Paulo 
9955b9c547cSRui Paulo 	return ret;
9965b9c547cSRui Paulo }
9975b9c547cSRui Paulo 
9985b9c547cSRui Paulo 
macsec_qca_enable_transmit_sa(void * priv,struct transmit_sa * sa)99985732ac8SCy Schubert static int macsec_qca_enable_transmit_sa(void *priv, struct transmit_sa *sa)
10005b9c547cSRui Paulo {
10015b9c547cSRui Paulo 	struct macsec_qca_data *drv = priv;
100285732ac8SCy Schubert 	int ret;
100385732ac8SCy Schubert 	u32 channel;
10045b9c547cSRui Paulo 
100585732ac8SCy Schubert 	ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel);
100685732ac8SCy Schubert 	if (ret != 0)
100785732ac8SCy Schubert 		return ret;
10085b9c547cSRui Paulo 
100985732ac8SCy Schubert 	wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel,
101085732ac8SCy Schubert 		   sa->an);
101185732ac8SCy Schubert 
101285732ac8SCy Schubert 	ret += nss_macsec_secy_tx_sa_en_set(drv->secy_id, channel, sa->an,
1013c1d255d3SCy Schubert 					    true);
10145b9c547cSRui Paulo 
10155b9c547cSRui Paulo 	return ret;
10165b9c547cSRui Paulo }
10175b9c547cSRui Paulo 
10185b9c547cSRui Paulo 
macsec_qca_disable_transmit_sa(void * priv,struct transmit_sa * sa)101985732ac8SCy Schubert static int macsec_qca_disable_transmit_sa(void *priv, struct transmit_sa *sa)
10205b9c547cSRui Paulo {
10215b9c547cSRui Paulo 	struct macsec_qca_data *drv = priv;
102285732ac8SCy Schubert 	int ret;
102385732ac8SCy Schubert 	u32 channel;
10245b9c547cSRui Paulo 
102585732ac8SCy Schubert 	ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel);
102685732ac8SCy Schubert 	if (ret != 0)
102785732ac8SCy Schubert 		return ret;
10285b9c547cSRui Paulo 
102985732ac8SCy Schubert 	wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel,
103085732ac8SCy Schubert 		   sa->an);
103185732ac8SCy Schubert 
103285732ac8SCy Schubert 	ret += nss_macsec_secy_tx_sa_en_set(drv->secy_id, channel, sa->an,
1033c1d255d3SCy Schubert 					    false);
10345b9c547cSRui Paulo 
10355b9c547cSRui Paulo 	return ret;
10365b9c547cSRui Paulo }
10375b9c547cSRui Paulo 
10385b9c547cSRui Paulo 
10395b9c547cSRui Paulo const struct wpa_driver_ops wpa_driver_macsec_qca_ops = {
10405b9c547cSRui Paulo 	.name = "macsec_qca",
10415b9c547cSRui Paulo 	.desc = "QCA MACsec Ethernet driver",
104285732ac8SCy Schubert 	.get_ssid = driver_wired_get_ssid,
104385732ac8SCy Schubert 	.get_bssid = driver_wired_get_bssid,
104485732ac8SCy Schubert 	.get_capa = driver_wired_get_capa,
10455b9c547cSRui Paulo 	.init = macsec_qca_init,
10465b9c547cSRui Paulo 	.deinit = macsec_qca_deinit,
1047206b73d0SCy Schubert 	.hapd_init = macsec_qca_hapd_init,
1048206b73d0SCy Schubert 	.hapd_deinit = macsec_qca_hapd_deinit,
1049206b73d0SCy Schubert 	.hapd_send_eapol = macsec_qca_send_eapol,
10505b9c547cSRui Paulo 
10515b9c547cSRui Paulo 	.macsec_init = macsec_qca_macsec_init,
10525b9c547cSRui Paulo 	.macsec_deinit = macsec_qca_macsec_deinit,
105385732ac8SCy Schubert 	.macsec_get_capability = macsec_qca_get_capability,
10545b9c547cSRui Paulo 	.enable_protect_frames = macsec_qca_enable_protect_frames,
10555b9c547cSRui Paulo 	.set_replay_protect = macsec_qca_set_replay_protect,
10565b9c547cSRui Paulo 	.set_current_cipher_suite = macsec_qca_set_current_cipher_suite,
10575b9c547cSRui Paulo 	.enable_controlled_port = macsec_qca_enable_controlled_port,
10585b9c547cSRui Paulo 	.get_receive_lowest_pn = macsec_qca_get_receive_lowest_pn,
10595b9c547cSRui Paulo 	.get_transmit_next_pn = macsec_qca_get_transmit_next_pn,
10605b9c547cSRui Paulo 	.set_transmit_next_pn = macsec_qca_set_transmit_next_pn,
10615b9c547cSRui Paulo 	.create_receive_sc = macsec_qca_create_receive_sc,
10625b9c547cSRui Paulo 	.delete_receive_sc = macsec_qca_delete_receive_sc,
10635b9c547cSRui Paulo 	.create_receive_sa = macsec_qca_create_receive_sa,
10645b9c547cSRui Paulo 	.enable_receive_sa = macsec_qca_enable_receive_sa,
10655b9c547cSRui Paulo 	.disable_receive_sa = macsec_qca_disable_receive_sa,
10665b9c547cSRui Paulo 	.create_transmit_sc = macsec_qca_create_transmit_sc,
10675b9c547cSRui Paulo 	.delete_transmit_sc = macsec_qca_delete_transmit_sc,
10685b9c547cSRui Paulo 	.create_transmit_sa = macsec_qca_create_transmit_sa,
10695b9c547cSRui Paulo 	.enable_transmit_sa = macsec_qca_enable_transmit_sa,
10705b9c547cSRui Paulo 	.disable_transmit_sa = macsec_qca_disable_transmit_sa,
10715b9c547cSRui Paulo };
1072