1/*
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.
6 *
7 * This software may be distributed under the terms of the BSD license.
8 * See README for more details.
9 */
10
11#include "includes.h"
12#include <sys/ioctl.h>
13#include <net/if.h>
14#include <inttypes.h>
15#ifdef __linux__
16#include <netpacket/packet.h>
17#include <net/if_arp.h>
18#include <net/if.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__) */
24#ifdef __sun__
25#include <sys/sockio.h>
26#endif /* __sun__ */
27
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"
33#include "driver.h"
34#include "driver_wired_common.h"
35
36#include "nss_macsec_secy.h"
37#include "nss_macsec_secy_rx.h"
38#include "nss_macsec_secy_tx.h"
39
40#define MAXSC 16
41
42/* TCI field definition */
43#define TCI_ES                0x40
44#define TCI_SC                0x20
45#define TCI_SCB               0x10
46#define TCI_E                 0x08
47#define TCI_C                 0x04
48
49#ifdef _MSC_VER
50#pragma pack(push, 1)
51#endif /* _MSC_VER */
52
53#ifdef _MSC_VER
54#pragma pack(pop)
55#endif /* _MSC_VER */
56
57struct channel_map {
58	struct ieee802_1x_mka_sci sci;
59};
60
61struct macsec_qca_data {
62	struct driver_wired_common_data common;
63
64	u32 secy_id;
65
66	/* shadow */
67	Boolean always_include_sci;
68	Boolean use_es;
69	Boolean use_scb;
70	Boolean protect_frames;
71	Boolean replay_protect;
72	u32 replay_window;
73
74	struct channel_map receive_channel_map[MAXSC];
75	struct channel_map transmit_channel_map[MAXSC];
76};
77
78
79static void __macsec_drv_init(struct macsec_qca_data *drv)
80{
81	int ret = 0;
82	fal_rx_ctl_filt_t rx_ctl_filt;
83	fal_tx_ctl_filt_t tx_ctl_filt;
84
85	wpa_printf(MSG_INFO, "%s: secy_id=%d", __func__, drv->secy_id);
86
87	/* Enable Secy and Let EAPoL bypass */
88	ret = nss_macsec_secy_en_set(drv->secy_id, TRUE);
89	if (ret)
90		wpa_printf(MSG_ERROR, "nss_macsec_secy_en_set: FAIL");
91
92	ret = nss_macsec_secy_sc_sa_mapping_mode_set(drv->secy_id,
93						     FAL_SC_SA_MAP_1_4);
94	if (ret)
95		wpa_printf(MSG_ERROR,
96			   "nss_macsec_secy_sc_sa_mapping_mode_set: FAIL");
97
98	os_memset(&rx_ctl_filt, 0, sizeof(rx_ctl_filt));
99	rx_ctl_filt.bypass = 1;
100	rx_ctl_filt.match_type = IG_CTL_COMPARE_ETHER_TYPE;
101	rx_ctl_filt.match_mask = 0xffff;
102	rx_ctl_filt.ether_type_da_range = 0x888e;
103	ret = nss_macsec_secy_rx_ctl_filt_set(drv->secy_id, 0, &rx_ctl_filt);
104	if (ret)
105		wpa_printf(MSG_ERROR, "nss_macsec_secy_rx_ctl_filt_set: FAIL");
106
107	os_memset(&tx_ctl_filt, 0, sizeof(tx_ctl_filt));
108	tx_ctl_filt.bypass = 1;
109	tx_ctl_filt.match_type = EG_CTL_COMPARE_ETHER_TYPE;
110	tx_ctl_filt.match_mask = 0xffff;
111	tx_ctl_filt.ether_type_da_range = 0x888e;
112	ret = nss_macsec_secy_tx_ctl_filt_set(drv->secy_id, 0, &tx_ctl_filt);
113	if (ret)
114		wpa_printf(MSG_ERROR, "nss_macsec_secy_tx_ctl_filt_set: FAIL");
115}
116
117
118static void __macsec_drv_deinit(struct macsec_qca_data *drv)
119{
120	nss_macsec_secy_en_set(drv->secy_id, FALSE);
121	nss_macsec_secy_rx_sc_del_all(drv->secy_id);
122	nss_macsec_secy_tx_sc_del_all(drv->secy_id);
123}
124
125
126static void * macsec_qca_init(void *ctx, const char *ifname)
127{
128	struct macsec_qca_data *drv;
129
130	drv = os_zalloc(sizeof(*drv));
131	if (drv == NULL)
132		return NULL;
133
134	/* Board specific settings */
135	if (os_memcmp("eth2", ifname, 4) == 0)
136		drv->secy_id = 1;
137	else if (os_memcmp("eth3", ifname, 4) == 0)
138		drv->secy_id = 2;
139	else
140		drv->secy_id = -1;
141
142	if (driver_wired_init_common(&drv->common, ifname, ctx) < 0) {
143		os_free(drv);
144		return NULL;
145	}
146
147	return drv;
148}
149
150
151static void macsec_qca_deinit(void *priv)
152{
153	struct macsec_qca_data *drv = priv;
154
155	driver_wired_deinit_common(&drv->common);
156	os_free(drv);
157}
158
159
160static int macsec_qca_macsec_init(void *priv, struct macsec_init_params *params)
161{
162	struct macsec_qca_data *drv = priv;
163
164	drv->always_include_sci = params->always_include_sci;
165	drv->use_es = params->use_es;
166	drv->use_scb = params->use_scb;
167
168	wpa_printf(MSG_DEBUG, "%s: es=%d, scb=%d, sci=%d",
169		   __func__, drv->use_es, drv->use_scb,
170		   drv->always_include_sci);
171
172	__macsec_drv_init(drv);
173
174	return 0;
175}
176
177
178static int macsec_qca_macsec_deinit(void *priv)
179{
180	struct macsec_qca_data *drv = priv;
181
182	wpa_printf(MSG_DEBUG, "%s", __func__);
183
184	__macsec_drv_deinit(drv);
185
186	return 0;
187}
188
189
190static int macsec_qca_get_capability(void *priv, enum macsec_cap *cap)
191{
192	wpa_printf(MSG_DEBUG, "%s", __func__);
193
194	*cap = MACSEC_CAP_INTEG_AND_CONF_0_30_50;
195
196	return 0;
197}
198
199
200static int macsec_qca_enable_protect_frames(void *priv, Boolean enabled)
201{
202	struct macsec_qca_data *drv = priv;
203	int ret = 0;
204
205	wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
206
207	drv->protect_frames = enabled;
208
209	return ret;
210}
211
212
213static int macsec_qca_set_replay_protect(void *priv, Boolean enabled,
214					 unsigned int window)
215{
216	struct macsec_qca_data *drv = priv;
217	int ret = 0;
218
219	wpa_printf(MSG_DEBUG, "%s: enabled=%d, win=%u",
220		   __func__, enabled, window);
221
222	drv->replay_protect = enabled;
223	drv->replay_window = window;
224
225	return ret;
226}
227
228
229static int macsec_qca_set_current_cipher_suite(void *priv, u64 cs)
230{
231	if (cs != CS_ID_GCM_AES_128) {
232		wpa_printf(MSG_ERROR,
233			   "%s: NOT supported CipherSuite: %016" PRIx64,
234			   __func__, cs);
235		return -1;
236	}
237
238	/* Support default Cipher Suite 0080020001000001 (GCM-AES-128) */
239	wpa_printf(MSG_DEBUG, "%s: default support aes-gcm-128", __func__);
240
241	return 0;
242}
243
244
245static int macsec_qca_enable_controlled_port(void *priv, Boolean enabled)
246{
247	struct macsec_qca_data *drv = priv;
248	int ret = 0;
249
250	wpa_printf(MSG_DEBUG, "%s: enable=%d", __func__, enabled);
251
252	ret += nss_macsec_secy_controlled_port_en_set(drv->secy_id, enabled);
253
254	return ret;
255}
256
257
258static int macsec_qca_lookup_channel(struct channel_map *map,
259				     struct ieee802_1x_mka_sci *sci,
260				     u32 *channel)
261{
262	u32 i;
263
264	for (i = 0; i < MAXSC; i++) {
265		if (os_memcmp(&map[i].sci, sci,
266			      sizeof(struct ieee802_1x_mka_sci)) == 0) {
267			*channel = i;
268			return 0;
269		}
270	}
271
272	return -1;
273}
274
275
276static void macsec_qca_register_channel(struct channel_map *map,
277					struct ieee802_1x_mka_sci *sci,
278					u32 channel)
279{
280	os_memcpy(&map[channel].sci, sci, sizeof(struct ieee802_1x_mka_sci));
281}
282
283
284static int macsec_qca_lookup_receive_channel(struct macsec_qca_data *drv,
285					     struct receive_sc *sc,
286					     u32 *channel)
287{
288	return macsec_qca_lookup_channel(drv->receive_channel_map, &sc->sci,
289					 channel);
290}
291
292
293static void macsec_qca_register_receive_channel(struct macsec_qca_data *drv,
294						struct receive_sc *sc,
295						u32 channel)
296{
297	macsec_qca_register_channel(drv->receive_channel_map, &sc->sci,
298				    channel);
299}
300
301
302static int macsec_qca_lookup_transmit_channel(struct macsec_qca_data *drv,
303					      struct transmit_sc *sc,
304					      u32 *channel)
305{
306	return macsec_qca_lookup_channel(drv->transmit_channel_map, &sc->sci,
307					 channel);
308}
309
310
311static void macsec_qca_register_transmit_channel(struct macsec_qca_data *drv,
312						 struct transmit_sc *sc,
313						 u32 channel)
314{
315	macsec_qca_register_channel(drv->transmit_channel_map, &sc->sci,
316				    channel);
317}
318
319
320static int macsec_qca_get_receive_lowest_pn(void *priv, struct receive_sa *sa)
321{
322	struct macsec_qca_data *drv = priv;
323	int ret = 0;
324	u32 next_pn = 0;
325	bool enabled = FALSE;
326	u32 win;
327	u32 channel;
328
329	ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel);
330	if (ret != 0)
331		return ret;
332
333	ret += nss_macsec_secy_rx_sa_next_pn_get(drv->secy_id, channel, sa->an,
334						 &next_pn);
335	ret += nss_macsec_secy_rx_sc_replay_protect_get(drv->secy_id, channel,
336							&enabled);
337	ret += nss_macsec_secy_rx_sc_anti_replay_window_get(drv->secy_id,
338							    channel, &win);
339
340	if (enabled)
341		sa->lowest_pn = (next_pn > win) ? (next_pn - win) : 1;
342	else
343		sa->lowest_pn = next_pn;
344
345	wpa_printf(MSG_DEBUG, "%s: lpn=0x%x", __func__, sa->lowest_pn);
346
347	return ret;
348}
349
350
351static int macsec_qca_get_transmit_next_pn(void *priv, struct transmit_sa *sa)
352{
353	struct macsec_qca_data *drv = priv;
354	int ret = 0;
355	u32 channel;
356
357	ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel);
358	if (ret != 0)
359		return ret;
360
361	ret += nss_macsec_secy_tx_sa_next_pn_get(drv->secy_id, channel, sa->an,
362						 &sa->next_pn);
363
364	wpa_printf(MSG_DEBUG, "%s: npn=0x%x", __func__, sa->next_pn);
365
366	return ret;
367}
368
369
370int macsec_qca_set_transmit_next_pn(void *priv, struct transmit_sa *sa)
371{
372	struct macsec_qca_data *drv = priv;
373	int ret = 0;
374	u32 channel;
375
376	ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel);
377	if (ret != 0)
378		return ret;
379
380	ret += nss_macsec_secy_tx_sa_next_pn_set(drv->secy_id, channel, sa->an,
381						 sa->next_pn);
382
383	wpa_printf(MSG_INFO, "%s: npn=0x%x", __func__, sa->next_pn);
384
385	return ret;
386}
387
388
389static int macsec_qca_get_available_receive_sc(void *priv, u32 *channel)
390{
391	struct macsec_qca_data *drv = priv;
392	int ret = 0;
393	u32 sc_ch = 0;
394	bool in_use = FALSE;
395
396	for (sc_ch = 0; sc_ch < MAXSC; sc_ch++) {
397		ret = nss_macsec_secy_rx_sc_in_used_get(drv->secy_id, sc_ch,
398							&in_use);
399		if (ret)
400			continue;
401
402		if (!in_use) {
403			*channel = sc_ch;
404			wpa_printf(MSG_DEBUG, "%s: channel=%d",
405				   __func__, *channel);
406			return 0;
407		}
408	}
409
410	wpa_printf(MSG_DEBUG, "%s: no available channel", __func__);
411
412	return -1;
413}
414
415
416static int macsec_qca_create_receive_sc(void *priv, struct receive_sc *sc,
417					unsigned int conf_offset,
418					int validation)
419{
420	struct macsec_qca_data *drv = priv;
421	int ret = 0;
422	fal_rx_prc_lut_t entry;
423	fal_rx_sc_validate_frame_e vf;
424	enum validate_frames validate_frames = validation;
425	u32 channel;
426	const u8 *sci_addr = sc->sci.addr;
427	u16 sci_port = be_to_host16(sc->sci.port);
428
429	ret = macsec_qca_get_available_receive_sc(priv, &channel);
430	if (ret != 0)
431		return ret;
432
433	wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel);
434
435	/* rx prc lut */
436	os_memset(&entry, 0, sizeof(entry));
437
438	os_memcpy(entry.sci, sci_addr, ETH_ALEN);
439	entry.sci[6] = (sci_port >> 8) & 0xf;
440	entry.sci[7] = sci_port & 0xf;
441	entry.sci_mask = 0xf;
442
443	entry.valid = 1;
444	entry.channel = channel;
445	entry.action = FAL_RX_PRC_ACTION_PROCESS;
446	entry.offset = conf_offset;
447
448	/* rx validate frame  */
449	if (validate_frames == Strict)
450		vf = FAL_RX_SC_VALIDATE_FRAME_STRICT;
451	else if (validate_frames == Checked)
452		vf = FAL_RX_SC_VALIDATE_FRAME_CHECK;
453	else
454		vf = FAL_RX_SC_VALIDATE_FRAME_DISABLED;
455
456	ret += nss_macsec_secy_rx_prc_lut_set(drv->secy_id, channel, &entry);
457	ret += nss_macsec_secy_rx_sc_create(drv->secy_id, channel);
458	ret += nss_macsec_secy_rx_sc_validate_frame_set(drv->secy_id, channel,
459							vf);
460	ret += nss_macsec_secy_rx_sc_replay_protect_set(drv->secy_id, channel,
461							drv->replay_protect);
462	ret += nss_macsec_secy_rx_sc_anti_replay_window_set(drv->secy_id,
463							    channel,
464							    drv->replay_window);
465
466	macsec_qca_register_receive_channel(drv, sc, channel);
467
468	return ret;
469}
470
471
472static int macsec_qca_delete_receive_sc(void *priv, struct receive_sc *sc)
473{
474	struct macsec_qca_data *drv = priv;
475	int ret;
476	fal_rx_prc_lut_t entry;
477	u32 channel;
478
479	ret = macsec_qca_lookup_receive_channel(priv, sc, &channel);
480	if (ret != 0)
481		return ret;
482
483	wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel);
484
485	/* rx prc lut */
486	os_memset(&entry, 0, sizeof(entry));
487
488	ret += nss_macsec_secy_rx_sc_del(drv->secy_id, channel);
489	ret += nss_macsec_secy_rx_prc_lut_set(drv->secy_id, channel, &entry);
490
491	return ret;
492}
493
494
495static int macsec_qca_create_receive_sa(void *priv, struct receive_sa *sa)
496{
497	struct macsec_qca_data *drv = priv;
498	int ret;
499	fal_rx_sak_t rx_sak;
500	int i = 0;
501	u32 channel;
502
503	ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel);
504	if (ret != 0)
505		return ret;
506
507	wpa_printf(MSG_DEBUG, "%s, channel=%d, an=%d, lpn=0x%x",
508		   __func__, channel, sa->an, sa->lowest_pn);
509
510	os_memset(&rx_sak, 0, sizeof(rx_sak));
511	for (i = 0; i < 16; i++)
512		rx_sak.sak[i] = sa->pkey->key[15 - i];
513
514	ret += nss_macsec_secy_rx_sa_create(drv->secy_id, channel, sa->an);
515	ret += nss_macsec_secy_rx_sak_set(drv->secy_id, channel, sa->an,
516					  &rx_sak);
517
518	return ret;
519}
520
521
522static int macsec_qca_enable_receive_sa(void *priv, struct receive_sa *sa)
523{
524	struct macsec_qca_data *drv = priv;
525	int ret;
526	u32 channel;
527
528	ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel);
529	if (ret != 0)
530		return ret;
531
532	wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel,
533		   sa->an);
534
535	ret += nss_macsec_secy_rx_sa_en_set(drv->secy_id, channel, sa->an,
536					    TRUE);
537
538	return ret;
539}
540
541
542static int macsec_qca_disable_receive_sa(void *priv, struct receive_sa *sa)
543{
544	struct macsec_qca_data *drv = priv;
545	int ret;
546	u32 channel;
547
548	ret = macsec_qca_lookup_receive_channel(priv, sa->sc, &channel);
549	if (ret != 0)
550		return ret;
551
552	wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel,
553		   sa->an);
554
555	ret += nss_macsec_secy_rx_sa_en_set(drv->secy_id, channel, sa->an,
556					    FALSE);
557
558	return ret;
559}
560
561
562static int macsec_qca_get_available_transmit_sc(void *priv, u32 *channel)
563{
564	struct macsec_qca_data *drv = priv;
565	u32 sc_ch = 0;
566	bool in_use = FALSE;
567
568	for (sc_ch = 0; sc_ch < MAXSC; sc_ch++) {
569		if (nss_macsec_secy_tx_sc_in_used_get(drv->secy_id, sc_ch,
570						      &in_use))
571			continue;
572
573		if (!in_use) {
574			*channel = sc_ch;
575			wpa_printf(MSG_DEBUG, "%s: channel=%d",
576				   __func__, *channel);
577			return 0;
578		}
579	}
580
581	wpa_printf(MSG_DEBUG, "%s: no avaiable channel", __func__);
582
583	return -1;
584}
585
586
587static int macsec_qca_create_transmit_sc(void *priv, struct transmit_sc *sc,
588					 unsigned int conf_offset)
589{
590	struct macsec_qca_data *drv = priv;
591	int ret;
592	fal_tx_class_lut_t entry;
593	u8 psci[ETH_ALEN + 2];
594	u32 channel;
595
596	ret = macsec_qca_get_available_transmit_sc(priv, &channel);
597	if (ret != 0)
598		return ret;
599
600	wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel);
601
602	/* class lut */
603	os_memset(&entry, 0, sizeof(entry));
604
605	entry.valid = 1;
606	entry.action = FAL_TX_CLASS_ACTION_FORWARD;
607	entry.channel = channel;
608
609	os_memcpy(psci, sc->sci.addr, ETH_ALEN);
610	psci[6] = (sc->sci.port >> 8) & 0xf;
611	psci[7] = sc->sci.port & 0xf;
612
613	ret += nss_macsec_secy_tx_class_lut_set(drv->secy_id, channel, &entry);
614	ret += nss_macsec_secy_tx_sc_create(drv->secy_id, channel, psci, 8);
615	ret += nss_macsec_secy_tx_sc_protect_set(drv->secy_id, channel,
616						 drv->protect_frames);
617	ret += nss_macsec_secy_tx_sc_confidentiality_offset_set(drv->secy_id,
618								channel,
619								conf_offset);
620
621	macsec_qca_register_transmit_channel(drv, sc, channel);
622
623	return ret;
624}
625
626
627static int macsec_qca_delete_transmit_sc(void *priv, struct transmit_sc *sc)
628{
629	struct macsec_qca_data *drv = priv;
630	int ret;
631	fal_tx_class_lut_t entry;
632	u32 channel;
633
634	ret = macsec_qca_lookup_transmit_channel(priv, sc, &channel);
635	if (ret != 0)
636		return ret;
637
638	wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel);
639
640	/* class lut */
641	os_memset(&entry, 0, sizeof(entry));
642
643	ret += nss_macsec_secy_tx_class_lut_set(drv->secy_id, channel, &entry);
644	ret += nss_macsec_secy_tx_sc_del(drv->secy_id, channel);
645
646	return ret;
647}
648
649
650static int macsec_qca_create_transmit_sa(void *priv, struct transmit_sa *sa)
651{
652	struct macsec_qca_data *drv = priv;
653	int ret;
654	u8 tci = 0;
655	fal_tx_sak_t tx_sak;
656	int i;
657	u32 channel;
658
659	ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel);
660	if (ret != 0)
661		return ret;
662
663	wpa_printf(MSG_DEBUG,
664		   "%s: channel=%d, an=%d, next_pn=0x%x, confidentiality=%d",
665		   __func__, channel, sa->an, sa->next_pn, sa->confidentiality);
666
667	if (drv->always_include_sci)
668		tci |= TCI_SC;
669	else if (drv->use_es)
670		tci |= TCI_ES;
671	else if (drv->use_scb)
672		tci |= TCI_SCB;
673
674	if (sa->confidentiality)
675		tci |= TCI_E | TCI_C;
676
677	os_memset(&tx_sak, 0, sizeof(tx_sak));
678	for (i = 0; i < 16; i++)
679		tx_sak.sak[i] = sa->pkey->key[15 - i];
680
681	ret += nss_macsec_secy_tx_sa_next_pn_set(drv->secy_id, channel, sa->an,
682						 sa->next_pn);
683	ret += nss_macsec_secy_tx_sak_set(drv->secy_id, channel, sa->an,
684					  &tx_sak);
685	ret += nss_macsec_secy_tx_sc_tci_7_2_set(drv->secy_id, channel,
686						 (tci >> 2));
687	ret += nss_macsec_secy_tx_sc_an_set(drv->secy_id, channel, sa->an);
688
689	return ret;
690}
691
692
693static int macsec_qca_enable_transmit_sa(void *priv, struct transmit_sa *sa)
694{
695	struct macsec_qca_data *drv = priv;
696	int ret;
697	u32 channel;
698
699	ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel);
700	if (ret != 0)
701		return ret;
702
703	wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel,
704		   sa->an);
705
706	ret += nss_macsec_secy_tx_sa_en_set(drv->secy_id, channel, sa->an,
707					    TRUE);
708
709	return ret;
710}
711
712
713static int macsec_qca_disable_transmit_sa(void *priv, struct transmit_sa *sa)
714{
715	struct macsec_qca_data *drv = priv;
716	int ret;
717	u32 channel;
718
719	ret = macsec_qca_lookup_transmit_channel(priv, sa->sc, &channel);
720	if (ret != 0)
721		return ret;
722
723	wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel,
724		   sa->an);
725
726	ret += nss_macsec_secy_tx_sa_en_set(drv->secy_id, channel, sa->an,
727					    FALSE);
728
729	return ret;
730}
731
732
733const struct wpa_driver_ops wpa_driver_macsec_qca_ops = {
734	.name = "macsec_qca",
735	.desc = "QCA MACsec Ethernet driver",
736	.get_ssid = driver_wired_get_ssid,
737	.get_bssid = driver_wired_get_bssid,
738	.get_capa = driver_wired_get_capa,
739	.init = macsec_qca_init,
740	.deinit = macsec_qca_deinit,
741
742	.macsec_init = macsec_qca_macsec_init,
743	.macsec_deinit = macsec_qca_macsec_deinit,
744	.macsec_get_capability = macsec_qca_get_capability,
745	.enable_protect_frames = macsec_qca_enable_protect_frames,
746	.set_replay_protect = macsec_qca_set_replay_protect,
747	.set_current_cipher_suite = macsec_qca_set_current_cipher_suite,
748	.enable_controlled_port = macsec_qca_enable_controlled_port,
749	.get_receive_lowest_pn = macsec_qca_get_receive_lowest_pn,
750	.get_transmit_next_pn = macsec_qca_get_transmit_next_pn,
751	.set_transmit_next_pn = macsec_qca_set_transmit_next_pn,
752	.create_receive_sc = macsec_qca_create_receive_sc,
753	.delete_receive_sc = macsec_qca_delete_receive_sc,
754	.create_receive_sa = macsec_qca_create_receive_sa,
755	.enable_receive_sa = macsec_qca_enable_receive_sa,
756	.disable_receive_sa = macsec_qca_disable_receive_sa,
757	.create_transmit_sc = macsec_qca_create_transmit_sc,
758	.delete_transmit_sc = macsec_qca_delete_transmit_sc,
759	.create_transmit_sa = macsec_qca_create_transmit_sa,
760	.enable_transmit_sa = macsec_qca_enable_transmit_sa,
761	.disable_transmit_sa = macsec_qca_disable_transmit_sa,
762};
763