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