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