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