10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51852Syz147064  * Common Development and Distribution License (the "License").
61852Syz147064  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
225895Syz147064  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #ifndef	_SYS_MAC_IMPL_H
270Sstevel@tonic-gate #define	_SYS_MAC_IMPL_H
280Sstevel@tonic-gate 
29*8275SEric Cheng #include <sys/modhash.h>
30*8275SEric Cheng #include <sys/mac_client.h>
31*8275SEric Cheng #include <sys/mac_provider.h>
322311Sseb #include <net/if.h>
33*8275SEric Cheng #include <sys/mac_flow_impl.h>
34*8275SEric Cheng #include <netinet/ip6.h>
350Sstevel@tonic-gate 
360Sstevel@tonic-gate #ifdef	__cplusplus
370Sstevel@tonic-gate extern "C" {
380Sstevel@tonic-gate #endif
390Sstevel@tonic-gate 
405895Syz147064 typedef struct mac_margin_req_s	mac_margin_req_t;
415895Syz147064 
425895Syz147064 struct mac_margin_req_s {
435895Syz147064 	mac_margin_req_t	*mmr_nextp;
445895Syz147064 	uint_t			mmr_ref;
455895Syz147064 	uint32_t		mmr_margin;
465895Syz147064 };
475895Syz147064 
48*8275SEric Cheng /* Generic linked chain type */
49*8275SEric Cheng typedef	struct mac_chain_s {
50*8275SEric Cheng 	struct mac_chain_s	*next;
51*8275SEric Cheng 	void			*item;
52*8275SEric Cheng } mac_chain_t;
53*8275SEric Cheng 
54*8275SEric Cheng /*
55*8275SEric Cheng  * Generic mac callback list manipulation structures and macros. The mac_cb_t
56*8275SEric Cheng  * represents a general callback list element embedded in a particular
57*8275SEric Cheng  * data structure such as a mac_notify_cb_t or a mac_promisc_impl_t.
58*8275SEric Cheng  * The mac_cb_info_t represents general information about list walkers.
59*8275SEric Cheng  * Please see the comments above mac_callback_add for more information.
60*8275SEric Cheng  */
61*8275SEric Cheng /* mcb_flags */
62*8275SEric Cheng #define	MCB_CONDEMNED		0x1		/* Logically deleted */
63*8275SEric Cheng #define	MCB_NOTIFY_CB_T		0x2
64*8275SEric Cheng #define	MCB_TX_NOTIFY_CB_T	0x4
650Sstevel@tonic-gate 
66*8275SEric Cheng typedef struct mac_cb_s {
67*8275SEric Cheng 	struct mac_cb_s		*mcb_nextp;	/* Linked list of callbacks */
68*8275SEric Cheng 	void			*mcb_objp;	/* Ptr to enclosing object  */
69*8275SEric Cheng 	size_t			mcb_objsize;	/* Sizeof the enclosing obj */
70*8275SEric Cheng 	uint_t			mcb_flags;
71*8275SEric Cheng } mac_cb_t;
720Sstevel@tonic-gate 
73*8275SEric Cheng typedef struct mac_cb_info_s {
74*8275SEric Cheng 	kmutex_t	*mcbi_lockp;
75*8275SEric Cheng 	kcondvar_t	mcbi_cv;
76*8275SEric Cheng 	uint_t		mcbi_del_cnt;		/* Deleted callback cnt */
77*8275SEric Cheng 	uint_t		mcbi_walker_cnt;	/* List walker count */
78*8275SEric Cheng } mac_cb_info_t;
79*8275SEric Cheng 
80*8275SEric Cheng typedef struct mac_notify_cb_s {
81*8275SEric Cheng 	mac_cb_t	mncb_link;		/* Linked list of callbacks */
82*8275SEric Cheng 	mac_notify_t	mncb_fn;		/* callback function */
83*8275SEric Cheng 	void		*mncb_arg;		/* callback argument */
84*8275SEric Cheng 	struct mac_impl_s *mncb_mip;
85*8275SEric Cheng } mac_notify_cb_t;
860Sstevel@tonic-gate 
87*8275SEric Cheng /*
88*8275SEric Cheng  * mac_callback_add(listinfo, listhead, listelement)
89*8275SEric Cheng  * mac_callback_remove(listinfo, listhead, listelement)
90*8275SEric Cheng  */
91*8275SEric Cheng typedef boolean_t (*mcb_func_t)(mac_cb_info_t *, mac_cb_t **, mac_cb_t *);
92*8275SEric Cheng 
93*8275SEric Cheng #define	MAC_CALLBACK_WALKER_INC(mcbi) {				\
94*8275SEric Cheng 	mutex_enter((mcbi)->mcbi_lockp);			\
95*8275SEric Cheng 	(mcbi)->mcbi_walker_cnt++;				\
96*8275SEric Cheng 	mutex_exit((mcbi)->mcbi_lockp);				\
97*8275SEric Cheng }
98*8275SEric Cheng 
99*8275SEric Cheng #define	MAC_CALLBACK_WALKER_INC_HELD(mcbi)	(mcbi)->mcbi_walker_cnt++;
1000Sstevel@tonic-gate 
101*8275SEric Cheng #define	MAC_CALLBACK_WALKER_DCR(mcbi, headp) {			\
102*8275SEric Cheng 	mac_cb_t	*rmlist;				\
103*8275SEric Cheng 								\
104*8275SEric Cheng 	mutex_enter((mcbi)->mcbi_lockp);			\
105*8275SEric Cheng 	if (--(mcbi)->mcbi_walker_cnt == 0 && (mcbi)->mcbi_del_cnt != 0) { \
106*8275SEric Cheng 		rmlist = mac_callback_walker_cleanup((mcbi), headp);	\
107*8275SEric Cheng 		mac_callback_free(rmlist);			\
108*8275SEric Cheng 		cv_broadcast(&(mcbi)->mcbi_cv);			\
109*8275SEric Cheng 	}							\
110*8275SEric Cheng 	mutex_exit((mcbi)->mcbi_lockp);				\
111*8275SEric Cheng }
1120Sstevel@tonic-gate 
113*8275SEric Cheng #define	MAC_PROMISC_WALKER_INC(mip)				\
114*8275SEric Cheng 	MAC_CALLBACK_WALKER_INC(&(mip)->mi_promisc_cb_info)
115*8275SEric Cheng 
116*8275SEric Cheng #define	MAC_PROMISC_WALKER_DCR(mip) {				\
117*8275SEric Cheng 	mac_cb_info_t	*mcbi;					\
118*8275SEric Cheng 								\
119*8275SEric Cheng 	mcbi = &(mip)->mi_promisc_cb_info;			\
120*8275SEric Cheng 	mutex_enter(mcbi->mcbi_lockp);				\
121*8275SEric Cheng 	if (--mcbi->mcbi_walker_cnt == 0 && mcbi->mcbi_del_cnt != 0) { \
122*8275SEric Cheng 		i_mac_promisc_walker_cleanup(mip);		\
123*8275SEric Cheng 		cv_broadcast(&mcbi->mcbi_cv);			\
124*8275SEric Cheng 	}							\
125*8275SEric Cheng 	mutex_exit(mcbi->mcbi_lockp);				\
126*8275SEric Cheng }
1270Sstevel@tonic-gate 
1282311Sseb typedef struct mactype_s {
1292311Sseb 	const char	*mt_ident;
1302311Sseb 	uint32_t	mt_ref;
1312311Sseb 	uint_t		mt_type;
1323147Sxc151355 	uint_t		mt_nativetype;
1332311Sseb 	size_t		mt_addr_length;
1342311Sseb 	uint8_t		*mt_brdcst_addr;
1352311Sseb 	mactype_ops_t	mt_ops;
1362311Sseb 	mac_stat_info_t	*mt_stats;	/* array of mac_stat_info_t elements */
1372311Sseb 	size_t		mt_statcount;	/* number of elements in mt_stats */
1386512Ssowmini 	mac_ndd_mapping_t *mt_mapping;
1396512Ssowmini 	size_t		mt_mappingcount;
1402311Sseb } mactype_t;
1410Sstevel@tonic-gate 
142*8275SEric Cheng /*
143*8275SEric Cheng  * Multiple rings implementation.
144*8275SEric Cheng  */
145*8275SEric Cheng typedef	enum {
146*8275SEric Cheng 	MAC_GROUP_STATE_UNINIT	= 0,	/* initial state of data structure */
147*8275SEric Cheng 	MAC_GROUP_STATE_REGISTERED,	/* hooked with h/w group */
148*8275SEric Cheng 	MAC_GROUP_STATE_RESERVED,	/* group is reserved and opened */
149*8275SEric Cheng 	MAC_GROUP_STATE_SHARED		/* default group shared among */
150*8275SEric Cheng 					/* multiple mac clients */
151*8275SEric Cheng } mac_group_state_t;
1525084Sjohnlev 
153*8275SEric Cheng typedef	struct mac_ring_s mac_ring_t;
154*8275SEric Cheng typedef	struct mac_group_s mac_group_t;
155*8275SEric Cheng 
156*8275SEric Cheng /*
157*8275SEric Cheng  * Ring data structure for ring control and management.
158*8275SEric Cheng  */
159*8275SEric Cheng typedef enum {
160*8275SEric Cheng 	MR_FREE,		/* Available for assignment to flows */
161*8275SEric Cheng 	MR_NEWLY_ADDED,		/* Just assigned to another group */
162*8275SEric Cheng 	MR_INUSE		/* Assigned to an SRS */
163*8275SEric Cheng } mac_ring_state_t;
164*8275SEric Cheng 
165*8275SEric Cheng /* mr_flag values */
166*8275SEric Cheng #define	MR_INCIPIENT	0x1
167*8275SEric Cheng #define	MR_CONDEMNED	0x2
168*8275SEric Cheng #define	MR_QUIESCE	0x4
169*8275SEric Cheng 
170*8275SEric Cheng struct mac_ring_s {
171*8275SEric Cheng 	int			mr_index;	/* index in the original list */
172*8275SEric Cheng 	mac_ring_type_t		mr_type;	/* ring type */
173*8275SEric Cheng 	mac_ring_t		*mr_next;	/* next ring in the chain */
174*8275SEric Cheng 	mac_group_handle_t	mr_gh;		/* reference to group */
175*8275SEric Cheng 
176*8275SEric Cheng 	mac_classify_type_t	mr_classify_type;	/* HW vs SW */
177*8275SEric Cheng 	struct mac_soft_ring_set_s *mr_srs;		/* associated SRS */
178*8275SEric Cheng 	uint_t			mr_refcnt;		/* Ring references */
179*8275SEric Cheng 	/* ring generation no. to guard against drivers using stale rings */
180*8275SEric Cheng 	uint64_t		mr_gen_num;
181*8275SEric Cheng 
182*8275SEric Cheng 	kmutex_t		mr_lock;
183*8275SEric Cheng 	kcondvar_t		mr_cv;			/* mr_lock */
184*8275SEric Cheng 	mac_ring_state_t	mr_state;		/* mr_lock */
185*8275SEric Cheng 	uint_t			mr_flag;		/* mr_lock */
186*8275SEric Cheng 
187*8275SEric Cheng 	mac_ring_info_t		mr_info;	/* driver supplied info */
188*8275SEric Cheng };
189*8275SEric Cheng #define	mr_driver		mr_info.mri_driver
190*8275SEric Cheng #define	mr_start		mr_info.mri_start
191*8275SEric Cheng #define	mr_stop			mr_info.mri_stop
192*8275SEric Cheng 
193*8275SEric Cheng #define	MAC_RING_MARK(mr, flag)		\
194*8275SEric Cheng 	(mr)->mr_flag |= flag;
195*8275SEric Cheng 
196*8275SEric Cheng #define	MAC_RING_UNMARK(mr, flag)	\
197*8275SEric Cheng 	(mr)->mr_flag &= ~flag;
198*8275SEric Cheng 
199*8275SEric Cheng /*
200*8275SEric Cheng  * Reference hold and release on mac_ring_t 'mr'
201*8275SEric Cheng  */
202*8275SEric Cheng #define	MR_REFHOLD_LOCKED(mr)		{		\
203*8275SEric Cheng 	ASSERT(MUTEX_HELD(&mr->mr_lock));		\
204*8275SEric Cheng 	(mr)->mr_refcnt++;				\
2055084Sjohnlev }
2065084Sjohnlev 
207*8275SEric Cheng #define	MR_REFRELE(mr)		{	 		\
208*8275SEric Cheng 	mutex_enter(&(mr)->mr_lock);			\
209*8275SEric Cheng 	ASSERT((mr)->mr_refcnt != 0);			\
210*8275SEric Cheng 	(mr)->mr_refcnt--;				\
211*8275SEric Cheng 	if ((mr)->mr_refcnt == 0 &&			\
212*8275SEric Cheng 	    ((mr)->mr_flag & (MR_CONDEMNED | MR_QUIESCE))) \
213*8275SEric Cheng 		cv_signal(&(mr)->mr_cv);		\
214*8275SEric Cheng 	mutex_exit(&(mr)->mr_lock);			\
2155084Sjohnlev }
2165084Sjohnlev 
217*8275SEric Cheng /*
218*8275SEric Cheng  * Per mac client flow information associated with a RX group.
219*8275SEric Cheng  * The entire structure is SL protected.
220*8275SEric Cheng  */
221*8275SEric Cheng typedef struct mac_grp_client {
222*8275SEric Cheng 	struct mac_grp_client		*mgc_next;
223*8275SEric Cheng 	struct mac_client_impl_s	*mgc_client;
224*8275SEric Cheng } mac_grp_client_t;
2255084Sjohnlev 
226*8275SEric Cheng #define	MAC_RX_GROUP_NO_CLIENT(g)	((g)->mrg_clients == NULL)
227*8275SEric Cheng 
228*8275SEric Cheng #define	MAC_RX_GROUP_ONLY_CLIENT(g)			\
229*8275SEric Cheng 	((((g)->mrg_clients != NULL) &&			\
230*8275SEric Cheng 	((g)->mrg_clients->mgc_next == NULL)) ?		\
231*8275SEric Cheng 	(g)->mrg_clients->mgc_client : NULL)
2326512Ssowmini 
2332311Sseb /*
234*8275SEric Cheng  * Common ring group data structure for ring control and management.
235*8275SEric Cheng  * The entire structure is SL protected
2362311Sseb  */
237*8275SEric Cheng struct mac_group_s {
238*8275SEric Cheng 	int			mrg_index;	/* index in the list */
239*8275SEric Cheng 	mac_ring_type_t		mrg_type;	/* ring type */
240*8275SEric Cheng 	mac_group_state_t	mrg_state;	/* state of the group */
241*8275SEric Cheng 	mac_group_t		*mrg_next;	/* next ring in the chain */
242*8275SEric Cheng 	mac_handle_t		mrg_mh;		/* reference to MAC */
243*8275SEric Cheng 	mac_ring_t		*mrg_rings;	/* grouped rings */
244*8275SEric Cheng 	uint_t			mrg_cur_count;	/* actual size of group */
245*8275SEric Cheng 
246*8275SEric Cheng 	mac_grp_client_t	*mrg_clients;	/* clients list */
247*8275SEric Cheng 
248*8275SEric Cheng 	struct mac_client_impl_s *mrg_tx_client; /* TX client pointer */
249*8275SEric Cheng 	mac_group_info_t	mrg_info;	/* driver supplied info */
250*8275SEric Cheng };
251*8275SEric Cheng 
252*8275SEric Cheng #define	mrg_driver		mrg_info.mgi_driver
253*8275SEric Cheng #define	mrg_start		mrg_info.mgi_start
254*8275SEric Cheng #define	mrg_stop		mrg_info.mgi_stop
255*8275SEric Cheng 
256*8275SEric Cheng #define	GROUP_INTR_HANDLE(g)		(g)->mrg_info.mgi_intr.mi_handle
257*8275SEric Cheng #define	GROUP_INTR_ENABLE_FUNC(g)	(g)->mrg_info.mgi_intr.mi_enable
258*8275SEric Cheng #define	GROUP_INTR_DISABLE_FUNC(g)	(g)->mrg_info.mgi_intr.mi_disable
259*8275SEric Cheng 
260*8275SEric Cheng #define	MAC_DEFAULT_GROUP(mh)		(((mac_impl_t *)mh)->mi_rx_groups)
261*8275SEric Cheng 
262*8275SEric Cheng #define	MAC_RING_TX_DEFAULT(mip, mp)			\
263*8275SEric Cheng 	((mip->mi_default_tx_ring == NULL) ?		\
264*8275SEric Cheng 	mip->mi_tx(mip->mi_driver, mp) :		\
265*8275SEric Cheng 	mac_ring_tx(mip->mi_default_tx_ring, mp))
2665895Syz147064 
267*8275SEric Cheng #define	MAC_TX(mip, ring, mp, mcip) {					\
268*8275SEric Cheng 	/*								\
269*8275SEric Cheng 	 * If the MAC client has a bound Hybrid I/O share,		\
270*8275SEric Cheng 	 * send the packet through the default tx ring, since		\
271*8275SEric Cheng 	 * the tx rings of this client are now mapped in the		\
272*8275SEric Cheng 	 * guest domain and not accessible from this domain.		\
273*8275SEric Cheng 	 */								\
274*8275SEric Cheng 	if (mcip->mci_share_bound || (ring == NULL))			\
275*8275SEric Cheng 		mp = MAC_RING_TX_DEFAULT(mip, mp);			\
276*8275SEric Cheng 	else								\
277*8275SEric Cheng 		mp = mac_ring_tx(ring, mp);				\
278*8275SEric Cheng }
279*8275SEric Cheng 
280*8275SEric Cheng /* mci_tx_flag */
281*8275SEric Cheng #define	MCI_TX_QUIESCE	0x1
282*8275SEric Cheng 
283*8275SEric Cheng typedef struct mac_factory_addr_s {
284*8275SEric Cheng 	boolean_t		mfa_in_use;
285*8275SEric Cheng 	uint8_t			mfa_addr[MAXMACADDRLEN];
286*8275SEric Cheng 	struct mac_client_impl_s	*mfa_client;
287*8275SEric Cheng } mac_factory_addr_t;
2885895Syz147064 
289*8275SEric Cheng typedef struct mac_mcast_addrs_s {
290*8275SEric Cheng 	struct mac_mcast_addrs_s	*mma_next;
291*8275SEric Cheng 	uint8_t				mma_addr[MAXMACADDRLEN];
292*8275SEric Cheng 	int				mma_ref;
293*8275SEric Cheng } mac_mcast_addrs_t;
294*8275SEric Cheng 
295*8275SEric Cheng typedef enum {
296*8275SEric Cheng 	MAC_ADDRESS_TYPE_UNICAST_CLASSIFIED = 1,	/* hardware steering */
297*8275SEric Cheng 	MAC_ADDRESS_TYPE_UNICAST_PROMISC		/* promiscuous mode */
298*8275SEric Cheng } mac_address_type_t;
299*8275SEric Cheng 
300*8275SEric Cheng typedef struct mac_impl_s mac_impl_t;
301*8275SEric Cheng 
302*8275SEric Cheng typedef struct mac_address_s {
303*8275SEric Cheng 	mac_address_type_t	ma_type;		/* address type */
304*8275SEric Cheng 	int			ma_nusers;		/* number of users */
305*8275SEric Cheng 							/* of that address */
306*8275SEric Cheng 	struct mac_address_s	*ma_next;		/* next address */
307*8275SEric Cheng 	uint8_t			ma_addr[MAXMACADDRLEN];	/* address value */
308*8275SEric Cheng 	size_t			ma_len;			/* address length */
309*8275SEric Cheng 	mac_group_t		*ma_group;		/* asscociated group */
310*8275SEric Cheng 	mac_impl_t		*ma_mip;		/* MAC handle */
311*8275SEric Cheng } mac_address_t;
312*8275SEric Cheng 
313*8275SEric Cheng extern krwlock_t i_mac_impl_lock;
314*8275SEric Cheng extern mod_hash_t *i_mac_impl_hash;
315*8275SEric Cheng extern kmem_cache_t *i_mac_impl_cachep;
316*8275SEric Cheng extern uint_t i_mac_impl_count;
3175895Syz147064 
318*8275SEric Cheng /*
319*8275SEric Cheng  * Each registered MAC is associated with a mac_impl_t structure. The
320*8275SEric Cheng  * structure represents the undelying hardware, in terms of definition,
321*8275SEric Cheng  * resources (transmit, receive rings etc.), callback functions etc. It
322*8275SEric Cheng  * also holds the table of MAC clients that are configured on the device.
323*8275SEric Cheng  * The table is used for classifying incoming packets in software.
324*8275SEric Cheng  *
325*8275SEric Cheng  * The protection scheme uses 2 elements, a coarse serialization mechanism
326*8275SEric Cheng  * called perimeter and a finer traditional lock based scheme. More details
327*8275SEric Cheng  * can be found in the big block comment in mac.c.
328*8275SEric Cheng  *
329*8275SEric Cheng  * The protection scheme for each member of the mac_impl_t is described below.
330*8275SEric Cheng  *
331*8275SEric Cheng  * Write Once Only (WO): Typically these don't change for the lifetime of the
332*8275SEric Cheng  * data structure. For example something in mac_impl_t that stays the same
333*8275SEric Cheng  * from mac_register to mac_unregister, or something in a mac_client_impl_t
334*8275SEric Cheng  * that stays the same from mac_client_open to mac_client_close.
335*8275SEric Cheng  *
336*8275SEric Cheng  * Serializer (SL): Protected by the Serializer. All SLOP operations on a
337*8275SEric Cheng  * mac endpoint go through the serializer. MTOPs don't care about reading
338*8275SEric Cheng  * these fields atomically.
339*8275SEric Cheng  *
340*8275SEric Cheng  * Lock: Traditional mutex/rw lock. Modify operations still go through the
341*8275SEric Cheng  * mac serializer, the lock helps synchronize readers with writers.
342*8275SEric Cheng  */
343*8275SEric Cheng struct mac_impl_s {
344*8275SEric Cheng 	krwlock_t		mi_rw_lock;
345*8275SEric Cheng 	char			mi_name[LIFNAMSIZ];	/* WO */
346*8275SEric Cheng 	uint32_t		mi_state_flags;
347*8275SEric Cheng 	void			*mi_driver;		/* Driver private, WO */
348*8275SEric Cheng 	mac_info_t		mi_info;		/* WO */
349*8275SEric Cheng 	mactype_t		*mi_type;		/* WO */
350*8275SEric Cheng 	void			*mi_pdata;		/* WO */
351*8275SEric Cheng 	size_t			mi_pdata_size;		/* WO */
352*8275SEric Cheng 	mac_callbacks_t		*mi_callbacks;		/* WO */
353*8275SEric Cheng 	dev_info_t		*mi_dip;		/* WO */
354*8275SEric Cheng 	uint32_t		mi_ref;			/* i_mac_impl_lock */
355*8275SEric Cheng 	uint_t			mi_active;		/* SL */
356*8275SEric Cheng 	link_state_t		mi_linkstate;		/* none */
357*8275SEric Cheng 	link_state_t		mi_lastlinkstate;	/* none */
358*8275SEric Cheng 	uint_t			mi_promisc;		/* SL */
359*8275SEric Cheng 	uint_t			mi_devpromisc;		/* SL */
360*8275SEric Cheng 	kmutex_t		mi_lock;
361*8275SEric Cheng 	uint8_t			mi_addr[MAXMACADDRLEN];	/* mi_rw_lock */
362*8275SEric Cheng 	uint8_t			mi_dstaddr[MAXMACADDRLEN]; /* mi_rw_lock */
3635895Syz147064 
364*8275SEric Cheng 	/*
365*8275SEric Cheng 	 * The mac perimeter. All client initiated create/modify operations
366*8275SEric Cheng 	 * on a mac end point go through this.
367*8275SEric Cheng 	 */
368*8275SEric Cheng 	kmutex_t		mi_perim_lock;
369*8275SEric Cheng 	kthread_t		*mi_perim_owner;	/* mi_perim_lock */
370*8275SEric Cheng 	uint_t			mi_perim_ocnt;		/* mi_perim_lock */
371*8275SEric Cheng 	kcondvar_t		mi_perim_cv;		/* mi_perim_lock */
3725895Syz147064 
373*8275SEric Cheng 	/* mac notification callbacks */
374*8275SEric Cheng 	kmutex_t		mi_notify_lock;
375*8275SEric Cheng 	mac_cb_info_t		mi_notify_cb_info;	/* mi_notify_lock */
376*8275SEric Cheng 	mac_cb_t		*mi_notify_cb_list;	/* mi_notify_lock */
377*8275SEric Cheng 	kthread_t		*mi_notify_thread;	/* mi_notify_lock */
378*8275SEric Cheng 	uint_t			mi_notify_bits;		/* mi_notify_lock */
379*8275SEric Cheng 
380*8275SEric Cheng 	uint32_t		mi_v12n_level;		/* Virt'ion readiness */
381*8275SEric Cheng 
382*8275SEric Cheng 	/*
383*8275SEric Cheng 	 * RX groups, ring capability
384*8275SEric Cheng 	 * Fields of this block are SL protected.
385*8275SEric Cheng 	 */
386*8275SEric Cheng 	mac_group_type_t	mi_rx_group_type;	/* grouping type */
387*8275SEric Cheng 	uint_t			mi_rx_group_count;
388*8275SEric Cheng 	mac_group_t		*mi_rx_groups;
3895895Syz147064 
390*8275SEric Cheng 	mac_capab_rings_t	mi_rx_rings_cap;
391*8275SEric Cheng 
392*8275SEric Cheng 	/*
393*8275SEric Cheng 	 * TX groups and ring capability, SL Protected.
394*8275SEric Cheng 	 */
395*8275SEric Cheng 	mac_group_type_t	mi_tx_group_type;	/* grouping type */
396*8275SEric Cheng 	uint_t			mi_tx_group_count;
397*8275SEric Cheng 	uint_t			mi_tx_group_free;
398*8275SEric Cheng 	mac_group_t		*mi_tx_groups;
399*8275SEric Cheng 
400*8275SEric Cheng 	mac_capab_rings_t	mi_tx_rings_cap;
401*8275SEric Cheng 
402*8275SEric Cheng 	mac_ring_handle_t	mi_default_tx_ring;
4035895Syz147064 
404*8275SEric Cheng 	/*
405*8275SEric Cheng 	 * MAC address list. SL protected.
406*8275SEric Cheng 	 */
407*8275SEric Cheng 	mac_address_t		*mi_addresses;
408*8275SEric Cheng 
409*8275SEric Cheng 	/*
410*8275SEric Cheng 	 * This MAC's table of sub-flows
411*8275SEric Cheng 	 */
412*8275SEric Cheng 	flow_tab_t		*mi_flow_tab;		/* WO */
413*8275SEric Cheng 
414*8275SEric Cheng 	kstat_t			*mi_ksp;		/* WO */
415*8275SEric Cheng 	uint_t			mi_kstat_count;		/* WO */
416*8275SEric Cheng 	uint_t			mi_nactiveclients;	/* SL */
417*8275SEric Cheng 
418*8275SEric Cheng 	/* for broadcast and multicast support */
419*8275SEric Cheng 	struct mac_mcast_addrs_s *mi_mcast_addrs;	/* mi_rw_lock */
420*8275SEric Cheng 	struct mac_bcast_grp_s *mi_bcast_grp;		/* mi_rw_lock */
421*8275SEric Cheng 	uint_t			mi_bcast_ngrps;		/* mi_rw_lock */
4225895Syz147064 
423*8275SEric Cheng 	/* list of MAC clients which opened this MAC */
424*8275SEric Cheng 	struct mac_client_impl_s *mi_clients_list;	/* mi_rw_lock */
425*8275SEric Cheng 	uint_t			mi_nclients;		/* mi_rw_lock */
426*8275SEric Cheng 
427*8275SEric Cheng 	uint32_t		mi_margin;		/* mi_rw_lock */
428*8275SEric Cheng 	uint_t			mi_sdu_min;		/* mi_rw_lock */
429*8275SEric Cheng 	uint_t			mi_sdu_max;		/* mi_rw_lock */
430*8275SEric Cheng 
431*8275SEric Cheng 	/*
432*8275SEric Cheng 	 * Cache of factory MAC addresses provided by the driver. If
433*8275SEric Cheng 	 * the driver doesn't provide multiple factory MAC addresses,
434*8275SEric Cheng 	 * the mi_factory_addr is set to NULL, and mi_factory_addr_num
435*8275SEric Cheng 	 * is set to zero.
436*8275SEric Cheng 	 */
437*8275SEric Cheng 	mac_factory_addr_t	*mi_factory_addr;	/* mi_rw_lock */
438*8275SEric Cheng 	uint_t			mi_factory_addr_num;	/* mi_rw_lock */
4395895Syz147064 
440*8275SEric Cheng 	/* for promiscuous mode support */
441*8275SEric Cheng 	kmutex_t		mi_promisc_lock;
442*8275SEric Cheng 	mac_cb_t		*mi_promisc_list;	/* mi_promisc_lock */
443*8275SEric Cheng 	mac_cb_info_t		mi_promisc_cb_info;	/* mi_promisc_lock */
444*8275SEric Cheng 
445*8275SEric Cheng 	/* cache of rings over this mac_impl */
446*8275SEric Cheng 	kmutex_t		mi_ring_lock;
447*8275SEric Cheng 	mac_ring_t		*mi_ring_freelist;	/* mi_ring_lock */
4485895Syz147064 
4495895Syz147064 	/*
450*8275SEric Cheng 	 * These are used for caching the properties, if any, for the
451*8275SEric Cheng 	 * primary MAC client. If the MAC client is not yet in place
452*8275SEric Cheng 	 * when the properties are set then we cache them here to be
453*8275SEric Cheng 	 * applied to the MAC client when it is created.
454*8275SEric Cheng 	 */
455*8275SEric Cheng 	mac_resource_props_t	mi_resource_props;	/* SL */
456*8275SEric Cheng 
457*8275SEric Cheng 	minor_t			mi_minor;		/* WO */
458*8275SEric Cheng 	dev_t			mi_phy_dev;		/* WO */
459*8275SEric Cheng 	uint32_t		mi_oref;		/* SL */
460*8275SEric Cheng 	uint32_t		mi_unsup_note;		/* WO */
461*8275SEric Cheng 	/*
4625895Syz147064 	 * List of margin value requests added by mac clients. This list is
4635895Syz147064 	 * sorted: the first one has the greatest value.
4645895Syz147064 	 */
4655895Syz147064 	mac_margin_req_t	*mi_mmrp;
4666512Ssowmini 	mac_priv_prop_t		*mi_priv_prop;
4676512Ssowmini 	uint_t			mi_priv_prop_count;
468*8275SEric Cheng 
469*8275SEric Cheng 	/*
470*8275SEric Cheng 	 * Hybrid I/O related definitions.
471*8275SEric Cheng 	 */
472*8275SEric Cheng 	mac_capab_share_t	mi_share_capab;
473*8275SEric Cheng 
474*8275SEric Cheng /* This should be the last block in this structure */
475*8275SEric Cheng #ifdef DEBUG
476*8275SEric Cheng #define	MAC_PERIM_STACK_DEPTH	15
477*8275SEric Cheng 	int			mi_perim_stack_depth;
478*8275SEric Cheng 	pc_t			mi_perim_stack[MAC_PERIM_STACK_DEPTH];
479*8275SEric Cheng #endif
480*8275SEric Cheng };
481*8275SEric Cheng 
482*8275SEric Cheng /* for mi_state_flags */
483*8275SEric Cheng #define	MIS_DISABLED		0x0001
484*8275SEric Cheng #define	MIS_IS_VNIC		0x0002
485*8275SEric Cheng #define	MIS_IS_AGGR		0x0004
486*8275SEric Cheng #define	MIS_NOTIFY_DONE		0x0008
487*8275SEric Cheng #define	MIS_EXCLUSIVE		0x0010
488*8275SEric Cheng #define	MIS_EXCLUSIVE_HELD	0x0020
489*8275SEric Cheng #define	MIS_LEGACY		0x0040
4902311Sseb 
4912311Sseb #define	mi_getstat	mi_callbacks->mc_getstat
4922311Sseb #define	mi_start	mi_callbacks->mc_start
4932311Sseb #define	mi_stop		mi_callbacks->mc_stop
4945895Syz147064 #define	mi_open		mi_callbacks->mc_open
4955895Syz147064 #define	mi_close	mi_callbacks->mc_close
4962311Sseb #define	mi_setpromisc	mi_callbacks->mc_setpromisc
4972311Sseb #define	mi_multicst	mi_callbacks->mc_multicst
4982311Sseb #define	mi_unicst	mi_callbacks->mc_unicst
4992311Sseb #define	mi_tx		mi_callbacks->mc_tx
5002311Sseb #define	mi_ioctl	mi_callbacks->mc_ioctl
5012311Sseb #define	mi_getcapab	mi_callbacks->mc_getcapab
5020Sstevel@tonic-gate 
503*8275SEric Cheng typedef struct mac_notify_task_arg {
504*8275SEric Cheng 	mac_impl_t		*mnt_mip;
505*8275SEric Cheng 	mac_notify_type_t	mnt_type;
506*8275SEric Cheng 	mac_ring_t		*mnt_ring;
507*8275SEric Cheng } mac_notify_task_arg_t;
508*8275SEric Cheng 
509*8275SEric Cheng typedef enum {
510*8275SEric Cheng 	MAC_RX_NO_RESERVE,
511*8275SEric Cheng 	MAC_RX_RESERVE_DEFAULT,
512*8275SEric Cheng 	MAC_RX_RESERVE_NONDEFAULT
513*8275SEric Cheng } mac_rx_group_reserve_type_t;
514*8275SEric Cheng 
515*8275SEric Cheng /*
516*8275SEric Cheng  * XXX All MAC_DBG_PRTs must be replaced with call to dtrace probes. For now
517*8275SEric Cheng  * it may be easier to have these printfs for easier debugging
518*8275SEric Cheng  */
519*8275SEric Cheng #ifdef DEBUG
520*8275SEric Cheng extern int mac_dbg;
521*8275SEric Cheng #define	MAC_DBG_PRT(a)	if (mac_dbg > 0) {(void) printf a; }
522*8275SEric Cheng #else
523*8275SEric Cheng #define	MAC_DBG_PRT(a)
524*8275SEric Cheng #endif
525*8275SEric Cheng 
526*8275SEric Cheng /*
527*8275SEric Cheng  * The mac_perim_handle_t is an opaque type that encodes the 'mip' pointer
528*8275SEric Cheng  * and whether internally a mac_open was done when acquiring the perimeter.
529*8275SEric Cheng  */
530*8275SEric Cheng #define	MAC_ENCODE_MPH(mph, mh, need_close)		\
531*8275SEric Cheng 	(mph) = (mac_perim_handle_t)((uintptr_t)(mh) | need_close)
532*8275SEric Cheng 
533*8275SEric Cheng #define	MAC_DECODE_MPH(mph, mip, need_close) {		\
534*8275SEric Cheng 	mip = (mac_impl_t *)(((uintptr_t)mph) & ~0x1);	\
535*8275SEric Cheng 	(need_close) = ((uintptr_t)mph & 0x1);		\
536*8275SEric Cheng }
537*8275SEric Cheng 
538*8275SEric Cheng typedef struct mac_client_impl_s mac_client_impl_t;
539*8275SEric Cheng 
5400Sstevel@tonic-gate extern void	mac_init(void);
5410Sstevel@tonic-gate extern int	mac_fini(void);
5420Sstevel@tonic-gate 
5430Sstevel@tonic-gate extern void	mac_stat_create(mac_impl_t *);
5440Sstevel@tonic-gate extern void	mac_stat_destroy(mac_impl_t *);
5452311Sseb extern uint64_t	mac_stat_default(mac_impl_t *, uint_t);
546*8275SEric Cheng extern void	mac_ndd_ioctl(mac_impl_t *, queue_t *, mblk_t *);
547*8275SEric Cheng extern void	mac_create_soft_ring_kstats(mac_impl_t *, int32_t);
548*8275SEric Cheng extern boolean_t mac_ip_hdr_length_v6(mblk_t *, ip6_t *, uint16_t *,
549*8275SEric Cheng     uint8_t *);
5500Sstevel@tonic-gate 
551*8275SEric Cheng extern mblk_t *mac_copymsgchain_cksum(mblk_t *);
552*8275SEric Cheng extern mblk_t *mac_fix_cksum(mblk_t *);
553*8275SEric Cheng extern void mac_packet_print(mac_handle_t, mblk_t *);
554*8275SEric Cheng extern void mac_rx_deliver(void *, mac_resource_handle_t, mblk_t *,
555*8275SEric Cheng     mac_header_info_t *);
556*8275SEric Cheng extern void mac_tx_notify(mac_impl_t *);
557*8275SEric Cheng 
558*8275SEric Cheng extern	boolean_t mac_callback_find(mac_cb_info_t *, mac_cb_t **, mac_cb_t *);
559*8275SEric Cheng extern	void	mac_callback_add(mac_cb_info_t *, mac_cb_t **, mac_cb_t *);
560*8275SEric Cheng extern	boolean_t mac_callback_remove(mac_cb_info_t *, mac_cb_t **, mac_cb_t *);
561*8275SEric Cheng extern	void	mac_callback_remove_wait(mac_cb_info_t *);
562*8275SEric Cheng extern	void	mac_callback_free(mac_cb_t *);
563*8275SEric Cheng extern	mac_cb_t *mac_callback_walker_cleanup(mac_cb_info_t *, mac_cb_t **);
564*8275SEric Cheng 
565*8275SEric Cheng /* in mac_bcast.c */
566*8275SEric Cheng extern void mac_bcast_init(void);
567*8275SEric Cheng extern void mac_bcast_fini(void);
568*8275SEric Cheng extern mac_impl_t *mac_bcast_grp_mip(void *);
569*8275SEric Cheng extern int mac_bcast_add(mac_client_impl_t *, const uint8_t *, uint16_t,
570*8275SEric Cheng     mac_addrtype_t);
571*8275SEric Cheng extern void mac_bcast_delete(mac_client_impl_t *, const uint8_t *, uint16_t);
572*8275SEric Cheng extern void mac_bcast_send(void *, void *, mblk_t *, boolean_t);
573*8275SEric Cheng extern void mac_bcast_grp_free(void *);
574*8275SEric Cheng extern void mac_bcast_refresh(mac_impl_t *, mac_multicst_t, void *,
575*8275SEric Cheng     boolean_t);
576*8275SEric Cheng extern void mac_client_bcast_refresh(mac_client_impl_t *, mac_multicst_t,
577*8275SEric Cheng     void *, boolean_t);
578*8275SEric Cheng 
579*8275SEric Cheng /*
580*8275SEric Cheng  * Grouping functions are used internally by MAC layer.
581*8275SEric Cheng  */
582*8275SEric Cheng extern int mac_group_addmac(mac_group_t *, const uint8_t *);
583*8275SEric Cheng extern int mac_group_remmac(mac_group_t *, const uint8_t *);
584*8275SEric Cheng extern int mac_rx_group_add_flow(mac_client_impl_t *, flow_entry_t *,
585*8275SEric Cheng     mac_group_t *);
586*8275SEric Cheng extern mblk_t *mac_ring_tx(mac_ring_handle_t, mblk_t *);
587*8275SEric Cheng extern mac_ring_t *mac_reserve_tx_ring(mac_impl_t *, mac_ring_t *);
588*8275SEric Cheng extern void mac_release_tx_ring(mac_ring_handle_t);
589*8275SEric Cheng extern mac_group_t *mac_reserve_tx_group(mac_impl_t *, mac_share_handle_t);
590*8275SEric Cheng extern void mac_release_tx_group(mac_impl_t *, mac_group_t *);
591*8275SEric Cheng 
592*8275SEric Cheng /*
593*8275SEric Cheng  * MAC address functions are used internally by MAC layer.
594*8275SEric Cheng  */
595*8275SEric Cheng extern mac_address_t *mac_find_macaddr(mac_impl_t *, uint8_t *);
596*8275SEric Cheng extern boolean_t mac_check_macaddr_shared(mac_address_t *);
597*8275SEric Cheng extern int mac_update_macaddr(mac_address_t *, uint8_t *);
598*8275SEric Cheng extern void mac_freshen_macaddr(mac_address_t *, uint8_t *);
599*8275SEric Cheng extern void mac_retrieve_macaddr(mac_address_t *, uint8_t *);
600*8275SEric Cheng extern void mac_init_macaddr(mac_impl_t *);
601*8275SEric Cheng extern void mac_fini_macaddr(mac_impl_t *);
602*8275SEric Cheng 
603*8275SEric Cheng /*
604*8275SEric Cheng  * Flow construction/destruction routines.
605*8275SEric Cheng  * Not meant to be used by mac clients.
606*8275SEric Cheng  */
607*8275SEric Cheng extern int mac_link_flow_init(mac_client_handle_t, flow_entry_t *);
608*8275SEric Cheng extern void mac_link_flow_clean(mac_client_handle_t, flow_entry_t *);
609*8275SEric Cheng 
610*8275SEric Cheng /*
611*8275SEric Cheng  * Called from mac_provider.c
612*8275SEric Cheng  */
613*8275SEric Cheng extern void mac_fanout_recompute(mac_impl_t *);
614*8275SEric Cheng 
615*8275SEric Cheng /*
616*8275SEric Cheng  * The following functions are used internally by the MAC layer to
617*8275SEric Cheng  * add/remove/update flows associated with a mac_impl_t. They should
618*8275SEric Cheng  * never be used directly by MAC clients.
619*8275SEric Cheng  */
620*8275SEric Cheng extern int mac_datapath_setup(mac_client_impl_t *, flow_entry_t *, uint32_t);
621*8275SEric Cheng extern void mac_datapath_teardown(mac_client_impl_t *, flow_entry_t *,
622*8275SEric Cheng     uint32_t);
623*8275SEric Cheng extern void mac_srs_group_setup(mac_client_impl_t *, flow_entry_t *,
624*8275SEric Cheng     mac_group_t *, uint32_t);
625*8275SEric Cheng extern void mac_srs_group_teardown(mac_client_impl_t *, flow_entry_t *,
626*8275SEric Cheng 	    uint32_t);
627*8275SEric Cheng extern int mac_rx_classify_flow_quiesce(flow_entry_t *, void *);
628*8275SEric Cheng extern int mac_rx_classify_flow_restart(flow_entry_t *, void *);
629*8275SEric Cheng extern void mac_tx_client_quiesce(mac_client_impl_t *, uint_t);
630*8275SEric Cheng extern void mac_tx_client_restart(mac_client_impl_t *);
631*8275SEric Cheng extern void mac_client_quiesce(mac_client_impl_t *);
632*8275SEric Cheng extern void mac_client_restart(mac_client_impl_t *);
633*8275SEric Cheng 
634*8275SEric Cheng extern void mac_flow_update_priority(mac_client_impl_t *, flow_entry_t *);
635*8275SEric Cheng 
636*8275SEric Cheng extern void mac_flow_rem_subflow(flow_entry_t *);
637*8275SEric Cheng extern void mac_rename_flow(flow_entry_t *, const char *);
638*8275SEric Cheng extern void mac_flow_set_name(flow_entry_t *, const char *);
639*8275SEric Cheng 
640*8275SEric Cheng extern mblk_t *mac_add_vlan_tag(mblk_t *, uint_t, uint16_t);
641*8275SEric Cheng extern mblk_t *mac_add_vlan_tag_chain(mblk_t *, uint_t, uint16_t);
642*8275SEric Cheng extern mblk_t *mac_strip_vlan_tag_chain(mblk_t *);
643*8275SEric Cheng extern void mac_pkt_drop(void *, mac_resource_handle_t, mblk_t *, boolean_t);
644*8275SEric Cheng extern mblk_t *mac_rx_flow(mac_handle_t, mac_resource_handle_t, mblk_t *);
645*8275SEric Cheng 
646*8275SEric Cheng extern void i_mac_share_alloc(mac_client_impl_t *);
647*8275SEric Cheng extern void i_mac_share_free(mac_client_impl_t *);
648*8275SEric Cheng extern void i_mac_perim_enter(mac_impl_t *);
649*8275SEric Cheng extern void i_mac_perim_exit(mac_impl_t *);
650*8275SEric Cheng extern int i_mac_perim_enter_nowait(mac_impl_t *);
651*8275SEric Cheng extern void i_mac_tx_srs_notify(mac_impl_t *, mac_ring_handle_t);
652*8275SEric Cheng extern int mac_hold(const char *, mac_impl_t **);
653*8275SEric Cheng extern void mac_rele(mac_impl_t *);
654*8275SEric Cheng extern int i_mac_disable(mac_impl_t *);
655*8275SEric Cheng extern void i_mac_notify(mac_impl_t *, mac_notify_type_t);
656*8275SEric Cheng extern void i_mac_notify_exit(mac_impl_t *);
657*8275SEric Cheng extern int mac_start(mac_impl_t *);
658*8275SEric Cheng extern void mac_stop(mac_impl_t *);
659*8275SEric Cheng extern void mac_rx_group_unmark(mac_group_t *, uint_t);
660*8275SEric Cheng extern void mac_tx_client_flush(mac_client_impl_t *);
661*8275SEric Cheng extern void mac_tx_client_block(mac_client_impl_t *);
662*8275SEric Cheng extern void mac_tx_client_unblock(mac_client_impl_t *);
663*8275SEric Cheng extern int i_mac_promisc_set(mac_impl_t *, boolean_t, mac_promisc_type_t);
664*8275SEric Cheng extern void i_mac_promisc_walker_cleanup(mac_impl_t *);
665*8275SEric Cheng extern mactype_t *mactype_getplugin(const char *);
666*8275SEric Cheng extern void mac_addr_factory_init(mac_impl_t *);
667*8275SEric Cheng extern void mac_addr_factory_fini(mac_impl_t *);
668*8275SEric Cheng extern void mac_register_priv_prop(mac_impl_t *, mac_priv_prop_t *, uint_t);
669*8275SEric Cheng extern void mac_unregister_priv_prop(mac_impl_t *);
670*8275SEric Cheng extern int mac_init_rings(mac_impl_t *, mac_ring_type_t);
671*8275SEric Cheng extern void mac_free_rings(mac_impl_t *, mac_ring_type_t);
672*8275SEric Cheng 
673*8275SEric Cheng extern int mac_start_group(mac_group_t *);
674*8275SEric Cheng extern void mac_stop_group(mac_group_t *);
675*8275SEric Cheng extern int mac_start_ring(mac_ring_t *);
676*8275SEric Cheng extern void mac_stop_ring(mac_ring_t *);
677*8275SEric Cheng extern int mac_add_macaddr(mac_impl_t *, mac_group_t *, uint8_t *);
678*8275SEric Cheng extern int mac_remove_macaddr(mac_address_t *);
679*8275SEric Cheng 
680*8275SEric Cheng extern void mac_set_rx_group_state(mac_group_t *, mac_group_state_t);
681*8275SEric Cheng extern void mac_rx_group_add_client(mac_group_t *, mac_client_impl_t *);
682*8275SEric Cheng extern void mac_rx_group_remove_client(mac_group_t *, mac_client_impl_t *)
683*8275SEric Cheng ;
684*8275SEric Cheng extern int i_mac_group_add_ring(mac_group_t *, mac_ring_t *, int);
685*8275SEric Cheng extern void i_mac_group_rem_ring(mac_group_t *, mac_ring_t *, boolean_t);
6866512Ssowmini 
6870Sstevel@tonic-gate #ifdef	__cplusplus
6880Sstevel@tonic-gate }
6890Sstevel@tonic-gate #endif
6900Sstevel@tonic-gate 
6910Sstevel@tonic-gate #endif	/* _SYS_MAC_IMPL_H */
692