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 (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright (c) 2018, Joyent, Inc.
  24  */
  25 
  26 #ifndef _SYS_MAC_IMPL_H
  27 #define _SYS_MAC_IMPL_H
  28 
  29 #include <sys/cpupart.h>
  30 #include <sys/modhash.h>
  31 #include <sys/mac_client.h>
  32 #include <sys/mac_provider.h>
  33 #include <sys/note.h>
  34 #include <sys/avl.h>
  35 #include <net/if.h>
  36 #include <sys/mac_flow_impl.h>
  37 #include <netinet/ip6.h>
  38 
  39 #ifdef  __cplusplus
  40 extern "C" {
  41 #endif
  42 
  43 /*
  44  * This is the first minor number available for MAC provider private
  45  * use.  This makes it possible to deliver a driver that is both a MAC
  46  * provider and a regular character/block device.  See PSARC 2009/380
  47  * for more detail about the construction of such devices.  The value
  48  * chosen leaves half of the 32-bit minor numbers (which are really
  49  * only 18 bits wide) available for driver private use.  Drivers can
  50  * easily identify their private number by the presence of this value
  51  * in the bits that make up the minor number, since its just the
  52  * highest bit available for such minor numbers.
  53  */
  54 #define MAC_PRIVATE_MINOR               ((MAXMIN32 + 1) / 2)
  55 
  56 /*
  57  * The maximum minor number that corresponds to a real instance.  This
  58  * limits the number of physical ports that a mac provider can offer.
  59  * Note that this macro must be synchronized with DLS_MAX_MINOR in
  60  * <sys/dls.h>
  61  */
  62 #define MAC_MAX_MINOR                   1000
  63 
  64 typedef struct mac_margin_req_s mac_margin_req_t;
  65 
  66 struct mac_margin_req_s {
  67         mac_margin_req_t        *mmr_nextp;
  68         uint_t                  mmr_ref;
  69         uint32_t                mmr_margin;
  70 };
  71 
  72 typedef struct mac_mtu_req_s mac_mtu_req_t;
  73 struct mac_mtu_req_s {
  74         mac_mtu_req_t           *mtr_nextp;
  75         uint_t                  mtr_ref;
  76         uint32_t                mtr_mtu;
  77 };
  78 
  79 /* Generic linked chain type */
  80 typedef struct mac_chain_s {
  81         struct mac_chain_s      *next;
  82         void                    *item;
  83 } mac_chain_t;
  84 
  85 /*
  86  * Generic mac callback list manipulation structures and macros. The mac_cb_t
  87  * represents a general callback list element embedded in a particular
  88  * data structure such as a mac_notify_cb_t or a mac_promisc_impl_t.
  89  * The mac_cb_info_t represents general information about list walkers.
  90  * Please see the comments above mac_callback_add for more information.
  91  */
  92 /* mcb_flags */
  93 #define MCB_CONDEMNED           0x1             /* Logically deleted */
  94 #define MCB_NOTIFY_CB_T         0x2
  95 #define MCB_TX_NOTIFY_CB_T      0x4
  96 
  97 extern boolean_t        mac_tx_serialize;
  98 
  99 typedef struct mac_cb_s {
 100         struct mac_cb_s         *mcb_nextp;     /* Linked list of callbacks */
 101         void                    *mcb_objp;      /* Ptr to enclosing object  */
 102         size_t                  mcb_objsize;    /* Sizeof the enclosing obj */
 103         uint_t                  mcb_flags;
 104 } mac_cb_t;
 105 
 106 typedef struct mac_cb_info_s {
 107         kmutex_t        *mcbi_lockp;
 108         kcondvar_t      mcbi_cv;
 109         uint_t          mcbi_del_cnt;           /* Deleted callback cnt */
 110         uint_t          mcbi_walker_cnt;        /* List walker count */
 111 } mac_cb_info_t;
 112 
 113 typedef struct mac_notify_cb_s {
 114         mac_cb_t        mncb_link;              /* Linked list of callbacks */
 115         mac_notify_t    mncb_fn;                /* callback function */
 116         void            *mncb_arg;              /* callback argument */
 117         struct mac_impl_s *mncb_mip;
 118 } mac_notify_cb_t;
 119 
 120 /*
 121  * mac_callback_add(listinfo, listhead, listelement)
 122  * mac_callback_remove(listinfo, listhead, listelement)
 123  */
 124 typedef boolean_t (*mcb_func_t)(mac_cb_info_t *, mac_cb_t **, mac_cb_t *);
 125 
 126 #define MAC_CALLBACK_WALKER_INC(mcbi) {                         \
 127         mutex_enter((mcbi)->mcbi_lockp);                     \
 128         (mcbi)->mcbi_walker_cnt++;                           \
 129         mutex_exit((mcbi)->mcbi_lockp);                              \
 130 }
 131 
 132 #define MAC_CALLBACK_WALKER_INC_HELD(mcbi)      (mcbi)->mcbi_walker_cnt++;
 133 
 134 #define MAC_CALLBACK_WALKER_DCR(mcbi, headp) {                  \
 135         mac_cb_t        *rmlist;                                \
 136                                                                 \
 137         mutex_enter((mcbi)->mcbi_lockp);                     \
 138         if (--(mcbi)->mcbi_walker_cnt == 0 && (mcbi)->mcbi_del_cnt != 0) { \
 139                 rmlist = mac_callback_walker_cleanup((mcbi), headp);    \
 140                 mac_callback_free(rmlist);                      \
 141                 cv_broadcast(&(mcbi)->mcbi_cv);                  \
 142         }                                                       \
 143         mutex_exit((mcbi)->mcbi_lockp);                              \
 144 }
 145 
 146 #define MAC_PROMISC_WALKER_INC(mip)                             \
 147         MAC_CALLBACK_WALKER_INC(&(mip)->mi_promisc_cb_info)
 148 
 149 #define MAC_PROMISC_WALKER_DCR(mip) {                           \
 150         mac_cb_info_t   *mcbi;                                  \
 151                                                                 \
 152         mcbi = &(mip)->mi_promisc_cb_info;                       \
 153         mutex_enter(mcbi->mcbi_lockp);                               \
 154         if (--mcbi->mcbi_walker_cnt == 0 && mcbi->mcbi_del_cnt != 0) { \
 155                 i_mac_promisc_walker_cleanup(mip);              \
 156                 cv_broadcast(&mcbi->mcbi_cv);                    \
 157         }                                                       \
 158         mutex_exit(mcbi->mcbi_lockp);                                \
 159 }
 160 
 161 typedef struct mactype_s {
 162         const char      *mt_ident;
 163         uint32_t        mt_ref;
 164         uint_t          mt_type;
 165         uint_t          mt_nativetype;
 166         size_t          mt_addr_length;
 167         uint8_t         *mt_brdcst_addr;
 168         mactype_ops_t   mt_ops;
 169         mac_stat_info_t *mt_stats;      /* array of mac_stat_info_t elements */
 170         size_t          mt_statcount;   /* number of elements in mt_stats */
 171         mac_ndd_mapping_t *mt_mapping;
 172         size_t          mt_mappingcount;
 173 } mactype_t;
 174 
 175 /*
 176  * Multiple rings implementation.
 177  */
 178 typedef enum {
 179         MAC_GROUP_STATE_UNINIT  = 0,    /* initial state of data structure */
 180         MAC_GROUP_STATE_REGISTERED,     /* hooked with h/w group */
 181         MAC_GROUP_STATE_RESERVED,       /* group is reserved and opened */
 182         MAC_GROUP_STATE_SHARED          /* default group shared among */
 183                                         /* multiple mac clients */
 184 } mac_group_state_t;
 185 
 186 typedef struct mac_ring_s mac_ring_t;
 187 typedef struct mac_group_s mac_group_t;
 188 
 189 /*
 190  * Ring data structure for ring control and management.
 191  */
 192 typedef enum {
 193         MR_FREE,                /* Available for assignment to flows */
 194         MR_NEWLY_ADDED,         /* Just assigned to another group */
 195         MR_INUSE                /* Assigned to an SRS */
 196 } mac_ring_state_t;
 197 
 198 /* mr_flag values */
 199 #define MR_INCIPIENT    0x1
 200 #define MR_CONDEMNED    0x2
 201 #define MR_QUIESCE      0x4
 202 
 203 typedef struct mac_impl_s mac_impl_t;
 204 
 205 struct mac_ring_s {
 206         int                     mr_index;       /* index in the original list */
 207         mac_ring_type_t         mr_type;        /* ring type */
 208         mac_ring_t              *mr_next;       /* next ring in the chain */
 209         mac_group_handle_t      mr_gh;          /* reference to group */
 210 
 211         mac_classify_type_t     mr_classify_type;
 212         struct mac_soft_ring_set_s *mr_srs;     /* associated SRS */
 213         mac_ring_handle_t       mr_prh; /* associated pseudo ring hdl */
 214 
 215         /*
 216          * Ring passthru callback and arguments. See the
 217          * MAC_PASSTHRU_CLASSIFIER comment in mac_provider.h.
 218          */
 219         mac_rx_t                mr_pt_fn;
 220         void                    *mr_pt_arg1;
 221         mac_resource_handle_t   mr_pt_arg2;
 222 
 223         uint_t                  mr_refcnt;      /* Ring references */
 224         /* ring generation no. to guard against drivers using stale rings */
 225         uint64_t                mr_gen_num;
 226 
 227         kstat_t                 *mr_ksp;        /* ring kstats */
 228         mac_impl_t              *mr_mip;        /* pointer to primary's mip */
 229 
 230         kmutex_t                mr_lock;
 231         kcondvar_t              mr_cv;                  /* mr_lock */
 232         mac_ring_state_t        mr_state;               /* mr_lock */
 233         uint_t                  mr_flag;                /* mr_lock */
 234 
 235         mac_ring_info_t         mr_info;        /* driver supplied info */
 236 };
 237 #define mr_driver               mr_info.mri_driver
 238 #define mr_start                mr_info.mri_start
 239 #define mr_stop                 mr_info.mri_stop
 240 #define mr_stat                 mr_info.mri_stat
 241 
 242 #define MAC_RING_MARK(mr, flag)         \
 243         (mr)->mr_flag |= flag;
 244 
 245 #define MAC_RING_UNMARK(mr, flag)       \
 246         (mr)->mr_flag &= ~flag;
 247 
 248 /*
 249  * Reference hold and release on mac_ring_t 'mr'
 250  */
 251 #define MR_REFHOLD_LOCKED(mr)           {               \
 252         ASSERT(MUTEX_HELD(&mr->mr_lock));                \
 253         (mr)->mr_refcnt++;                           \
 254 }
 255 
 256 #define MR_REFRELE(mr)          {                       \
 257         mutex_enter(&(mr)->mr_lock);                     \
 258         ASSERT((mr)->mr_refcnt != 0);                        \
 259         (mr)->mr_refcnt--;                           \
 260         if ((mr)->mr_refcnt == 0 &&                  \
 261             ((mr)->mr_flag & (MR_CONDEMNED | MR_QUIESCE))) \
 262                 cv_signal(&(mr)->mr_cv);         \
 263         mutex_exit(&(mr)->mr_lock);                      \
 264 }
 265 
 266 /*
 267  * Used to attach MAC clients to an Rx group. The members are SL
 268  * protected.
 269  */
 270 typedef struct mac_grp_client {
 271         struct mac_grp_client           *mgc_next;
 272         struct mac_client_impl_s        *mgc_client;
 273 } mac_grp_client_t;
 274 
 275 #define MAC_GROUP_NO_CLIENT(g)  ((g)->mrg_clients == NULL)
 276 
 277 #define MAC_GROUP_ONLY_CLIENT(g)                        \
 278         ((((g)->mrg_clients != NULL) &&                      \
 279         ((g)->mrg_clients->mgc_next == NULL)) ?           \
 280         (g)->mrg_clients->mgc_client : NULL)
 281 
 282 #define MAC_GROUP_HW_VLAN(g)                            \
 283         (((g) != NULL) &&                               \
 284         ((g)->mrg_info.mgi_addvlan != NULL) &&               \
 285         ((g)->mrg_info.mgi_remvlan != NULL))
 286 
 287 /*
 288  * Common ring group data structure for ring control and management.
 289  * The entire structure is SL protected.
 290  */
 291 struct mac_group_s {
 292         int                     mrg_index;      /* index in the list */
 293         mac_ring_type_t         mrg_type;       /* ring type */
 294         mac_group_state_t       mrg_state;      /* state of the group */
 295         mac_group_t             *mrg_next;      /* next group in the chain */
 296         mac_handle_t            mrg_mh;         /* reference to MAC */
 297         mac_ring_t              *mrg_rings;     /* grouped rings */
 298         uint_t                  mrg_cur_count;  /* actual size of group */
 299 
 300         mac_grp_client_t        *mrg_clients;   /* clients list */
 301 
 302         mac_group_info_t        mrg_info;       /* driver supplied info */
 303 };
 304 
 305 #define mrg_driver              mrg_info.mgi_driver
 306 #define mrg_start               mrg_info.mgi_start
 307 #define mrg_stop                mrg_info.mgi_stop
 308 
 309 #define GROUP_INTR_HANDLE(g)            (g)->mrg_info.mgi_intr.mi_handle
 310 #define GROUP_INTR_ENABLE_FUNC(g)       (g)->mrg_info.mgi_intr.mi_enable
 311 #define GROUP_INTR_DISABLE_FUNC(g)      (g)->mrg_info.mgi_intr.mi_disable
 312 
 313 #define MAC_RING_TX(mhp, rh, mp, rest) {                                \
 314         mac_ring_handle_t mrh = rh;                                     \
 315         mac_impl_t *mimpl = (mac_impl_t *)mhp;                          \
 316         /*                                                              \
 317          * Send packets through a selected tx ring, or through the      \
 318          * default handler if there is no selected ring.                \
 319          */                                                             \
 320         if (mrh == NULL)                                                \
 321                 mrh = mimpl->mi_default_tx_ring;                     \
 322         if (mrh == NULL) {                                              \
 323                 rest = mimpl->mi_tx(mimpl->mi_driver, mp);                \
 324         } else {                                                        \
 325                 rest = mac_hwring_tx(mrh, mp);                          \
 326         }                                                               \
 327 }
 328 
 329 /*
 330  * This is the final stop before reaching the underlying driver
 331  * or aggregation, so this is where the bridging hook is implemented.
 332  * Packets that are bridged will return through mac_bridge_tx(), with
 333  * rh nulled out if the bridge chooses to send output on a different
 334  * link due to forwarding.
 335  */
 336 #define MAC_TX(mip, rh, mp, src_mcip) {                                 \
 337         mac_ring_handle_t       rhandle = (rh);                         \
 338         /*                                                              \
 339          * If there is a bound Hybrid I/O share, send packets through   \
 340          * the default tx ring. (When there's a bound Hybrid I/O share, \
 341          * the tx rings of this client are mapped in the guest domain   \
 342          * and not accessible from here.)                               \
 343          */                                                             \
 344         _NOTE(CONSTANTCONDITION)                                        \
 345         if ((src_mcip)->mci_state_flags & MCIS_SHARE_BOUND)              \
 346                 rhandle = (mip)->mi_default_tx_ring;                 \
 347         if (mip->mi_promisc_list != NULL)                            \
 348                 mac_promisc_dispatch(mip, mp, src_mcip);                \
 349         /*                                                              \
 350          * Grab the proper transmit pointer and handle. Special         \
 351          * optimization: we can test mi_bridge_link itself atomically,  \
 352          * and if that indicates no bridge send packets through tx ring.\
 353          */                                                             \
 354         if (mip->mi_bridge_link == NULL) {                           \
 355                 MAC_RING_TX(mip, rhandle, mp, mp);                      \
 356         } else {                                                        \
 357                 mp = mac_bridge_tx(mip, rhandle, mp);                   \
 358         }                                                               \
 359 }
 360 
 361 /* mci_tx_flag */
 362 #define MCI_TX_QUIESCE  0x1
 363 
 364 typedef struct mac_factory_addr_s {
 365         boolean_t               mfa_in_use;
 366         uint8_t                 mfa_addr[MAXMACADDRLEN];
 367         struct mac_client_impl_s        *mfa_client;
 368 } mac_factory_addr_t;
 369 
 370 typedef struct mac_mcast_addrs_s {
 371         struct mac_mcast_addrs_s        *mma_next;
 372         uint8_t                         mma_addr[MAXMACADDRLEN];
 373         int                             mma_ref;
 374 } mac_mcast_addrs_t;
 375 
 376 typedef enum {
 377         MAC_ADDRESS_TYPE_UNICAST_CLASSIFIED = 1,        /* HW classification */
 378         MAC_ADDRESS_TYPE_UNICAST_PROMISC                /* promiscuous mode */
 379 } mac_address_type_t;
 380 
 381 typedef struct mac_vlan_s {
 382         struct mac_vlan_s       *mv_next;
 383         uint16_t                mv_vid;
 384 } mac_vlan_t;
 385 
 386 typedef struct mac_address_s {
 387         mac_address_type_t      ma_type;                /* address type */
 388         int                     ma_nusers;              /* num users of addr */
 389         struct mac_address_s    *ma_next;               /* next address */
 390         uint8_t                 ma_addr[MAXMACADDRLEN]; /* address value */
 391         size_t                  ma_len;                 /* address length */
 392         mac_vlan_t              *ma_vlans;              /* VLANs on this addr */
 393         boolean_t               ma_untagged;            /* accept untagged? */
 394         mac_group_t             *ma_group;              /* asscociated group */
 395         mac_impl_t              *ma_mip;                /* MAC handle */
 396 } mac_address_t;
 397 
 398 extern krwlock_t i_mac_impl_lock;
 399 extern mod_hash_t *i_mac_impl_hash;
 400 extern kmem_cache_t *i_mac_impl_cachep;
 401 extern uint_t i_mac_impl_count;
 402 
 403 /*
 404  * Each registered MAC is associated with a mac_impl_t structure. The
 405  * structure represents the undelying hardware, in terms of definition,
 406  * resources (transmit, receive rings etc.), callback functions etc. It
 407  * also holds the table of MAC clients that are configured on the device.
 408  * The table is used for classifying incoming packets in software.
 409  *
 410  * The protection scheme uses 2 elements, a coarse serialization mechanism
 411  * called perimeter and a finer traditional lock based scheme. More details
 412  * can be found in the big block comment in mac.c.
 413  *
 414  * The protection scheme for each member of the mac_impl_t is described below.
 415  *
 416  * Write Once Only (WO): Typically these don't change for the lifetime of the
 417  * data structure. For example something in mac_impl_t that stays the same
 418  * from mac_register to mac_unregister, or something in a mac_client_impl_t
 419  * that stays the same from mac_client_open to mac_client_close.
 420  *
 421  * Serializer (SL): Protected by the Serializer. All SLOP operations on a
 422  * mac endpoint go through the serializer. MTOPs don't care about reading
 423  * these fields atomically.
 424  *
 425  * Lock: Traditional mutex/rw lock. Modify operations still go through the
 426  * mac serializer, the lock helps synchronize readers with writers.
 427  */
 428 struct mac_impl_s {
 429         krwlock_t               mi_rw_lock;
 430         list_node_t             mi_node;
 431         char                    mi_name[LIFNAMSIZ];     /* WO */
 432         uint32_t                mi_state_flags;
 433         void                    *mi_driver;             /* Driver private, WO */
 434         mac_info_t              mi_info;                /* WO */
 435         mactype_t               *mi_type;               /* WO */
 436         void                    *mi_pdata;              /* WO */
 437         size_t                  mi_pdata_size;          /* WO */
 438         mac_callbacks_t         *mi_callbacks;          /* WO */
 439         dev_info_t              *mi_dip;                /* WO */
 440         uint32_t                mi_ref;                 /* i_mac_impl_lock */
 441         uint_t                  mi_active;              /* SL */
 442         link_state_t            mi_linkstate;           /* none */
 443         link_state_t            mi_lowlinkstate;        /* none */
 444         link_state_t            mi_lastlowlinkstate;    /* none */
 445         uint_t                  mi_devpromisc;          /* SL */
 446         uint8_t                 mi_addr[MAXMACADDRLEN]; /* mi_rw_lock */
 447         uint8_t                 mi_dstaddr[MAXMACADDRLEN]; /* mi_rw_lock */
 448         boolean_t               mi_dstaddr_set;
 449 
 450         /*
 451          * The mac perimeter. All client initiated create/modify operations
 452          * on a mac end point go through this.
 453          */
 454         kmutex_t                mi_perim_lock;
 455         kthread_t               *mi_perim_owner;        /* mi_perim_lock */
 456         uint_t                  mi_perim_ocnt;          /* mi_perim_lock */
 457         kcondvar_t              mi_perim_cv;            /* mi_perim_lock */
 458 
 459         /* mac notification callbacks */
 460         kmutex_t                mi_notify_lock;
 461         mac_cb_info_t           mi_notify_cb_info;      /* mi_notify_lock */
 462         mac_cb_t                *mi_notify_cb_list;     /* mi_notify_lock */
 463         kthread_t               *mi_notify_thread;      /* mi_notify_lock */
 464         uint_t                  mi_notify_bits;         /* mi_notify_lock */
 465 
 466         uint32_t                mi_v12n_level;          /* Virt'ion readiness */
 467 
 468         /*
 469          * RX groups, ring capability
 470          * Fields of this block are SL protected.
 471          */
 472         mac_group_type_t        mi_rx_group_type;       /* grouping type */
 473         uint_t                  mi_rx_group_count;
 474         mac_group_t             *mi_rx_groups;
 475         mac_group_t             *mi_rx_donor_grp;
 476         uint_t                  mi_rxrings_rsvd;
 477         uint_t                  mi_rxrings_avail;
 478         uint_t                  mi_rxhwclnt_avail;
 479         uint_t                  mi_rxhwclnt_used;
 480 
 481         mac_capab_rings_t       mi_rx_rings_cap;
 482 
 483         /*
 484          * TX groups and ring capability, SL Protected.
 485          */
 486         mac_group_type_t        mi_tx_group_type;       /* grouping type */
 487         uint_t                  mi_tx_group_count;
 488         uint_t                  mi_tx_group_free;
 489         mac_group_t             *mi_tx_groups;
 490         mac_capab_rings_t       mi_tx_rings_cap;
 491         uint_t                  mi_txrings_rsvd;
 492         uint_t                  mi_txrings_avail;
 493         uint_t                  mi_txhwclnt_avail;
 494         uint_t                  mi_txhwclnt_used;
 495 
 496         mac_ring_handle_t       mi_default_tx_ring;
 497 
 498         /*
 499          * Transceiver capabilities. SL protected.
 500          */
 501         mac_capab_transceiver_t mi_transceiver;
 502 
 503         /*
 504          * LED Capability information. SL protected.
 505          */
 506         mac_led_mode_t          mi_led_modes;
 507         mac_capab_led_t         mi_led;
 508 
 509         /*
 510          * MAC address and VLAN lists. SL protected.
 511          */
 512         mac_address_t           *mi_addresses;
 513 
 514         /*
 515          * This MAC's table of sub-flows
 516          */
 517         flow_tab_t              *mi_flow_tab;           /* WO */
 518 
 519         kstat_t                 *mi_ksp;                /* WO */
 520         uint_t                  mi_kstat_count;         /* WO */
 521         uint_t                  mi_nactiveclients;      /* SL */
 522 
 523         /* for broadcast and multicast support */
 524         struct mac_mcast_addrs_s *mi_mcast_addrs;       /* mi_rw_lock */
 525         struct mac_bcast_grp_s *mi_bcast_grp;           /* mi_rw_lock */
 526         uint_t                  mi_bcast_ngrps;         /* mi_rw_lock */
 527 
 528         /* list of MAC clients which opened this MAC */
 529         struct mac_client_impl_s *mi_clients_list;      /* mi_rw_lock */
 530         uint_t                  mi_nclients;            /* mi_rw_lock */
 531         struct mac_client_impl_s *mi_single_active_client; /* mi_rw_lock */
 532 
 533         uint32_t                mi_margin;              /* mi_rw_lock */
 534         uint_t                  mi_sdu_min;             /* mi_rw_lock */
 535         uint_t                  mi_sdu_max;             /* mi_rw_lock */
 536         uint_t                  mi_sdu_multicast;       /* mi_rw_lock */
 537 
 538         /*
 539          * Cache of factory MAC addresses provided by the driver. If
 540          * the driver doesn't provide multiple factory MAC addresses,
 541          * the mi_factory_addr is set to NULL, and mi_factory_addr_num
 542          * is set to zero.
 543          */
 544         mac_factory_addr_t      *mi_factory_addr;       /* mi_rw_lock */
 545         uint_t                  mi_factory_addr_num;    /* mi_rw_lock */
 546 
 547         /* for promiscuous mode support */
 548         kmutex_t                mi_promisc_lock;
 549         mac_cb_t                *mi_promisc_list;       /* mi_promisc_lock */
 550         mac_cb_info_t           mi_promisc_cb_info;     /* mi_promisc_lock */
 551 
 552         /* cache of rings over this mac_impl */
 553         kmutex_t                mi_ring_lock;
 554         mac_ring_t              *mi_ring_freelist;      /* mi_ring_lock */
 555 
 556         /*
 557          * These are used for caching the properties, if any, for the
 558          * primary MAC client. If the MAC client is not yet in place
 559          * when the properties are set then we cache them here to be
 560          * applied to the MAC client when it is created.
 561          */
 562         mac_resource_props_t    mi_resource_props;      /* SL */
 563         uint16_t                mi_pvid;                /* SL */
 564 
 565         minor_t                 mi_minor;               /* WO */
 566         uint32_t                mi_oref;                /* SL */
 567         mac_capab_legacy_t      mi_capab_legacy;        /* WO */
 568         dev_t                   mi_phy_dev;             /* WO */
 569 
 570         /*
 571          * List of margin value requests added by mac clients. This list is
 572          * sorted: the first one has the greatest value.
 573          */
 574         mac_margin_req_t        *mi_mmrp;
 575         mac_mtu_req_t           *mi_mtrp;
 576         char                    **mi_priv_prop;
 577         uint_t                  mi_priv_prop_count;
 578 
 579         /*
 580          * Hybrid I/O related definitions.
 581          */
 582         mac_capab_share_t       mi_share_capab;
 583 
 584         /*
 585          * Bridging hooks and limit values.  Uses mutex and reference counts
 586          * (bridging only) for data path.  Limits need no synchronization.
 587          */
 588         mac_handle_t            mi_bridge_link;
 589         kmutex_t                mi_bridge_lock;
 590         uint32_t                mi_llimit;
 591         uint32_t                mi_ldecay;
 592 
 593 /* This should be the last block in this structure */
 594 #ifdef DEBUG
 595 #define MAC_PERIM_STACK_DEPTH   15
 596         int                     mi_perim_stack_depth;
 597         pc_t                    mi_perim_stack[MAC_PERIM_STACK_DEPTH];
 598 #endif
 599 };
 600 
 601 /*
 602  * The default TX group is the last one in the list.
 603  */
 604 #define MAC_DEFAULT_TX_GROUP(mip)       \
 605         (mip)->mi_tx_groups + (mip)->mi_tx_group_count
 606 
 607 /*
 608  * The default RX group is the first one in the list
 609  */
 610 #define MAC_DEFAULT_RX_GROUP(mip)       (mip)->mi_rx_groups
 611 
 612 /* Reserved RX rings */
 613 #define MAC_RX_RING_RESERVED(m, cnt)    {       \
 614         ASSERT((m)->mi_rxrings_avail >= (cnt));   \
 615         (m)->mi_rxrings_rsvd += (cnt);               \
 616         (m)->mi_rxrings_avail -= (cnt);              \
 617 }
 618 
 619 /* Released RX rings */
 620 #define MAC_RX_RING_RELEASED(m, cnt)    {       \
 621         ASSERT((m)->mi_rxrings_rsvd >= (cnt));    \
 622         (m)->mi_rxrings_rsvd -= (cnt);               \
 623         (m)->mi_rxrings_avail += (cnt);              \
 624 }
 625 
 626 /* Reserved a RX group */
 627 #define MAC_RX_GRP_RESERVED(m)  {               \
 628         ASSERT((m)->mi_rxhwclnt_avail > 0);       \
 629         (m)->mi_rxhwclnt_avail--;            \
 630         (m)->mi_rxhwclnt_used++;             \
 631 }
 632 
 633 /* Released a RX group */
 634 #define MAC_RX_GRP_RELEASED(m)  {               \
 635         ASSERT((m)->mi_rxhwclnt_used > 0);        \
 636         (m)->mi_rxhwclnt_avail++;            \
 637         (m)->mi_rxhwclnt_used--;             \
 638 }
 639 
 640 /* Reserved TX rings */
 641 #define MAC_TX_RING_RESERVED(m, cnt)    {       \
 642         ASSERT((m)->mi_txrings_avail >= (cnt));   \
 643         (m)->mi_txrings_rsvd += (cnt);               \
 644         (m)->mi_txrings_avail -= (cnt);              \
 645 }
 646 /* Released TX rings */
 647 #define MAC_TX_RING_RELEASED(m, cnt)    {       \
 648         ASSERT((m)->mi_txrings_rsvd >= (cnt));    \
 649         (m)->mi_txrings_rsvd -= (cnt);               \
 650         (m)->mi_txrings_avail += (cnt);              \
 651 }
 652 
 653 /* Reserved a TX group */
 654 #define MAC_TX_GRP_RESERVED(m)  {               \
 655         ASSERT((m)->mi_txhwclnt_avail > 0);       \
 656         (m)->mi_txhwclnt_avail--;            \
 657         (m)->mi_txhwclnt_used++;             \
 658 }
 659 
 660 /* Released a TX group */
 661 #define MAC_TX_GRP_RELEASED(m)  {               \
 662         ASSERT((m)->mi_txhwclnt_used > 0);        \
 663         (m)->mi_txhwclnt_avail++;            \
 664         (m)->mi_txhwclnt_used--;             \
 665 }
 666 
 667 /* for mi_state_flags */
 668 #define MIS_DISABLED            0x0001
 669 #define MIS_IS_VNIC             0x0002
 670 #define MIS_IS_AGGR             0x0004
 671 #define MIS_NOTIFY_DONE         0x0008
 672 #define MIS_EXCLUSIVE           0x0010
 673 #define MIS_EXCLUSIVE_HELD      0x0020
 674 #define MIS_LEGACY              0x0040
 675 #define MIS_NO_ACTIVE           0x0080
 676 #define MIS_POLL_DISABLE        0x0100
 677 
 678 #define mi_getstat      mi_callbacks->mc_getstat
 679 #define mi_start        mi_callbacks->mc_start
 680 #define mi_stop         mi_callbacks->mc_stop
 681 #define mi_open         mi_callbacks->mc_open
 682 #define mi_close        mi_callbacks->mc_close
 683 #define mi_setpromisc   mi_callbacks->mc_setpromisc
 684 #define mi_multicst     mi_callbacks->mc_multicst
 685 #define mi_unicst       mi_callbacks->mc_unicst
 686 #define mi_tx           mi_callbacks->mc_tx
 687 #define mi_ioctl        mi_callbacks->mc_ioctl
 688 #define mi_getcapab     mi_callbacks->mc_getcapab
 689 
 690 typedef struct mac_notify_task_arg {
 691         mac_impl_t              *mnt_mip;
 692         mac_notify_type_t       mnt_type;
 693         mac_ring_t              *mnt_ring;
 694 } mac_notify_task_arg_t;
 695 
 696 /*
 697  * The mac_perim_handle_t is an opaque type that encodes the 'mip' pointer
 698  * and whether internally a mac_open was done when acquiring the perimeter.
 699  */
 700 #define MAC_ENCODE_MPH(mph, mh, need_close)             \
 701         (mph) = (mac_perim_handle_t)((uintptr_t)(mh) | need_close)
 702 
 703 #define MAC_DECODE_MPH(mph, mip, need_close) {          \
 704         mip = (mac_impl_t *)(((uintptr_t)mph) & ~0x1);      \
 705         (need_close) = ((uintptr_t)mph & 0x1);              \
 706 }
 707 
 708 /*
 709  * Type of property information that can be returned by a driver.
 710  * Valid flags of the pr_flags of the mac_prop_info_t data structure.
 711  */
 712 #define MAC_PROP_INFO_DEFAULT   0x0001
 713 #define MAC_PROP_INFO_RANGE     0x0002
 714 #define MAC_PROP_INFO_PERM      0x0004
 715 
 716 /*
 717  * Property information. pr_flags is a combination of one of the
 718  * MAC_PROP_INFO_* flags, it is reset by the framework before invoking
 719  * the driver's prefix_propinfo() entry point.
 720  *
 721  * Drivers should use MAC_PROP_INFO_SET_*() macros to provide
 722  * information about a property.
 723  */
 724 typedef struct mac_prop_info_state_s {
 725         uint8_t                 pr_flags;
 726         uint8_t                 pr_perm;
 727         uint8_t                 pr_errno;
 728         void                    *pr_default;
 729         size_t                  pr_default_size;
 730         mac_propval_range_t     *pr_range;
 731         uint_t                  pr_range_cur_count;
 732 } mac_prop_info_state_t;
 733 
 734 #define MAC_PROTECT_ENABLED(mcip, type) \
 735         (((mcip)->mci_flent-> \
 736         fe_resource_props.mrp_mask & MRP_PROTECT) != 0 && \
 737         ((mcip)->mci_flent-> \
 738         fe_resource_props.mrp_protect.mp_types & (type)) != 0)
 739 
 740 typedef struct mac_client_impl_s mac_client_impl_t;
 741 
 742 extern void     mac_init(void);
 743 extern int      mac_fini(void);
 744 
 745 extern void     mac_ndd_ioctl(mac_impl_t *, queue_t *, mblk_t *);
 746 extern boolean_t mac_ip_hdr_length_v6(ip6_t *, uint8_t *, uint16_t *,
 747     uint8_t *, ip6_frag_t **);
 748 
 749 extern mblk_t *mac_copymsgchain_cksum(mblk_t *);
 750 extern mblk_t *mac_fix_cksum(mblk_t *);
 751 extern void mac_packet_print(mac_handle_t, mblk_t *);
 752 extern void mac_rx_deliver(void *, mac_resource_handle_t, mblk_t *,
 753     mac_header_info_t *);
 754 extern void mac_tx_notify(mac_impl_t *);
 755 
 756 extern  boolean_t mac_callback_find(mac_cb_info_t *, mac_cb_t **, mac_cb_t *);
 757 extern  void    mac_callback_add(mac_cb_info_t *, mac_cb_t **, mac_cb_t *);
 758 extern  boolean_t mac_callback_remove(mac_cb_info_t *, mac_cb_t **, mac_cb_t *);
 759 extern  void    mac_callback_remove_wait(mac_cb_info_t *);
 760 extern  void    mac_callback_free(mac_cb_t *);
 761 extern  mac_cb_t *mac_callback_walker_cleanup(mac_cb_info_t *, mac_cb_t **);
 762 
 763 /* in mac_bcast.c */
 764 extern void mac_bcast_init(void);
 765 extern void mac_bcast_fini(void);
 766 extern mac_impl_t *mac_bcast_grp_mip(void *);
 767 extern int mac_bcast_add(mac_client_impl_t *, const uint8_t *, uint16_t,
 768     mac_addrtype_t);
 769 extern void mac_bcast_delete(mac_client_impl_t *, const uint8_t *, uint16_t);
 770 extern void mac_bcast_send(void *, void *, mblk_t *, boolean_t);
 771 extern void mac_bcast_grp_free(void *);
 772 extern void mac_bcast_refresh(mac_impl_t *, mac_multicst_t, void *,
 773     boolean_t);
 774 extern void mac_client_bcast_refresh(mac_client_impl_t *, mac_multicst_t,
 775     void *, boolean_t);
 776 
 777 /*
 778  * Grouping functions are used internally by MAC layer.
 779  */
 780 extern int mac_group_addmac(mac_group_t *, const uint8_t *);
 781 extern int mac_group_remmac(mac_group_t *, const uint8_t *);
 782 extern int mac_group_addvlan(mac_group_t *, uint16_t);
 783 extern int mac_group_remvlan(mac_group_t *, uint16_t);
 784 extern int mac_rx_group_add_flow(mac_client_impl_t *, flow_entry_t *,
 785     mac_group_t *);
 786 extern mblk_t *mac_hwring_tx(mac_ring_handle_t, mblk_t *);
 787 extern mblk_t *mac_bridge_tx(mac_impl_t *, mac_ring_handle_t, mblk_t *);
 788 extern mac_group_t *mac_reserve_rx_group(mac_client_impl_t *, uint8_t *,
 789     boolean_t);
 790 extern void mac_release_rx_group(mac_client_impl_t *, mac_group_t *);
 791 extern int mac_rx_switch_group(mac_client_impl_t *, mac_group_t *,
 792     mac_group_t *);
 793 extern mac_ring_t *mac_reserve_tx_ring(mac_impl_t *, mac_ring_t *);
 794 extern mac_group_t *mac_reserve_tx_group(mac_client_impl_t *, boolean_t);
 795 extern void mac_release_tx_group(mac_client_impl_t *, mac_group_t *);
 796 extern void mac_tx_switch_group(mac_client_impl_t *, mac_group_t *,
 797     mac_group_t *);
 798 extern void mac_rx_switch_grp_to_sw(mac_group_t *);
 799 
 800 /*
 801  * MAC address functions are used internally by MAC layer.
 802  */
 803 extern mac_address_t *mac_find_macaddr(mac_impl_t *, uint8_t *);
 804 extern mac_address_t *mac_find_macaddr_vlan(mac_impl_t *, uint8_t *, uint16_t);
 805 extern boolean_t mac_check_macaddr_shared(mac_address_t *);
 806 extern int mac_update_macaddr(mac_address_t *, uint8_t *);
 807 extern void mac_freshen_macaddr(mac_address_t *, uint8_t *);
 808 extern void mac_retrieve_macaddr(mac_address_t *, uint8_t *);
 809 extern void mac_init_macaddr(mac_impl_t *);
 810 extern void mac_fini_macaddr(mac_impl_t *);
 811 
 812 /*
 813  * Flow construction/destruction routines.
 814  * Not meant to be used by mac clients.
 815  */
 816 extern int mac_link_flow_init(mac_client_handle_t, flow_entry_t *);
 817 extern void mac_link_flow_clean(mac_client_handle_t, flow_entry_t *);
 818 
 819 /*
 820  * Fanout update routines called when the link speed of the NIC changes
 821  * or when a MAC client's share is unbound.
 822  */
 823 extern void mac_fanout_recompute_client(mac_client_impl_t *, cpupart_t *);
 824 extern void mac_fanout_recompute(mac_impl_t *);
 825 
 826 /*
 827  * The following functions are used internally by the MAC layer to
 828  * add/remove/update flows associated with a mac_impl_t. They should
 829  * never be used directly by MAC clients.
 830  */
 831 extern int mac_datapath_setup(mac_client_impl_t *, flow_entry_t *, uint32_t);
 832 extern void mac_datapath_teardown(mac_client_impl_t *, flow_entry_t *,
 833     uint32_t);
 834 extern void mac_rx_srs_group_setup(mac_client_impl_t *, flow_entry_t *,
 835     uint32_t);
 836 extern void mac_tx_srs_group_setup(mac_client_impl_t *, flow_entry_t *,
 837     uint32_t);
 838 extern void mac_rx_srs_group_teardown(flow_entry_t *, boolean_t);
 839 extern void mac_tx_srs_group_teardown(mac_client_impl_t *, flow_entry_t *,
 840             uint32_t);
 841 extern int mac_rx_classify_flow_quiesce(flow_entry_t *, void *);
 842 extern int mac_rx_classify_flow_restart(flow_entry_t *, void *);
 843 extern void mac_client_quiesce(mac_client_impl_t *);
 844 extern void mac_client_restart(mac_client_impl_t *);
 845 
 846 extern void mac_flow_update_priority(mac_client_impl_t *, flow_entry_t *);
 847 
 848 extern void mac_flow_rem_subflow(flow_entry_t *);
 849 extern void mac_rename_flow(flow_entry_t *, const char *);
 850 extern void mac_flow_set_name(flow_entry_t *, const char *);
 851 
 852 extern mblk_t *mac_add_vlan_tag(mblk_t *, uint_t, uint16_t);
 853 extern mblk_t *mac_add_vlan_tag_chain(mblk_t *, uint_t, uint16_t);
 854 extern mblk_t *mac_strip_vlan_tag_chain(mblk_t *);
 855 extern void mac_pkt_drop(void *, mac_resource_handle_t, mblk_t *, boolean_t);
 856 extern mblk_t *mac_rx_flow(mac_handle_t, mac_resource_handle_t, mblk_t *);
 857 
 858 extern void i_mac_share_alloc(mac_client_impl_t *);
 859 extern void i_mac_share_free(mac_client_impl_t *);
 860 extern void i_mac_perim_enter(mac_impl_t *);
 861 extern void i_mac_perim_exit(mac_impl_t *);
 862 extern int i_mac_perim_enter_nowait(mac_impl_t *);
 863 extern void i_mac_tx_srs_notify(mac_impl_t *, mac_ring_handle_t);
 864 extern int mac_hold(const char *, mac_impl_t **);
 865 extern void mac_rele(mac_impl_t *);
 866 extern int i_mac_disable(mac_impl_t *);
 867 extern void i_mac_notify(mac_impl_t *, mac_notify_type_t);
 868 extern void i_mac_notify_exit(mac_impl_t *);
 869 extern void mac_rx_group_unmark(mac_group_t *, uint_t);
 870 extern void mac_tx_client_flush(mac_client_impl_t *);
 871 extern void mac_tx_client_block(mac_client_impl_t *);
 872 extern void mac_tx_client_unblock(mac_client_impl_t *);
 873 extern void mac_tx_invoke_callbacks(mac_client_impl_t *, mac_tx_cookie_t);
 874 extern int i_mac_promisc_set(mac_impl_t *, boolean_t);
 875 extern void i_mac_promisc_walker_cleanup(mac_impl_t *);
 876 extern mactype_t *mactype_getplugin(const char *);
 877 extern void mac_addr_factory_init(mac_impl_t *);
 878 extern void mac_addr_factory_fini(mac_impl_t *);
 879 extern void mac_register_priv_prop(mac_impl_t *, char **);
 880 extern void mac_unregister_priv_prop(mac_impl_t *);
 881 extern int mac_init_rings(mac_impl_t *, mac_ring_type_t);
 882 extern void mac_free_rings(mac_impl_t *, mac_ring_type_t);
 883 extern void mac_compare_ddi_handle(mac_group_t *, uint_t, mac_ring_t *);
 884 
 885 extern int mac_start_group(mac_group_t *);
 886 extern void mac_stop_group(mac_group_t *);
 887 extern int mac_start_ring(mac_ring_t *);
 888 extern void mac_stop_ring(mac_ring_t *);
 889 extern int mac_add_macaddr_vlan(mac_impl_t *, mac_group_t *, uint8_t *,
 890     uint16_t, boolean_t);
 891 extern int mac_remove_macaddr_vlan(mac_address_t *, uint16_t);
 892 
 893 extern void mac_set_group_state(mac_group_t *, mac_group_state_t);
 894 extern void mac_group_add_client(mac_group_t *, mac_client_impl_t *);
 895 extern void mac_group_remove_client(mac_group_t *, mac_client_impl_t *);
 896 
 897 extern int i_mac_group_add_ring(mac_group_t *, mac_ring_t *, int);
 898 extern void i_mac_group_rem_ring(mac_group_t *, mac_ring_t *, boolean_t);
 899 extern int mac_group_ring_modify(mac_client_impl_t *, mac_group_t *,
 900     mac_group_t *);
 901 extern void mac_poll_state_change(mac_handle_t, boolean_t);
 902 
 903 extern mac_group_state_t mac_group_next_state(mac_group_t *,
 904     mac_client_impl_t **, mac_group_t *, boolean_t);
 905 
 906 extern mblk_t *mac_protect_check(mac_client_handle_t, mblk_t *);
 907 extern int mac_protect_set(mac_client_handle_t, mac_resource_props_t *);
 908 extern boolean_t mac_protect_enabled(mac_client_handle_t, uint32_t);
 909 extern int mac_protect_validate(mac_resource_props_t *);
 910 extern void mac_protect_update(mac_resource_props_t *, mac_resource_props_t *);
 911 extern void mac_protect_update_mac_token(mac_client_impl_t *);
 912 extern void mac_protect_intercept_dynamic(mac_client_impl_t *, mblk_t *);
 913 extern void mac_protect_flush_dynamic(mac_client_impl_t *);
 914 extern void mac_protect_cancel_timer(mac_client_impl_t *);
 915 extern void mac_protect_init(mac_client_impl_t *);
 916 extern void mac_protect_fini(mac_client_impl_t *);
 917 
 918 extern int mac_set_resources(mac_handle_t, mac_resource_props_t *);
 919 extern void mac_get_resources(mac_handle_t, mac_resource_props_t *);
 920 extern void mac_get_effective_resources(mac_handle_t, mac_resource_props_t *);
 921 extern void mac_set_promisc_filtered(mac_client_handle_t, boolean_t);
 922 extern boolean_t mac_get_promisc_filtered(mac_client_handle_t);
 923 
 924 extern cpupart_t *mac_pset_find(mac_resource_props_t *, boolean_t *);
 925 extern void mac_set_pool_effective(boolean_t, cpupart_t *,
 926     mac_resource_props_t *, mac_resource_props_t *);
 927 extern void mac_set_rings_effective(mac_client_impl_t *);
 928 extern mac_client_impl_t *mac_check_primary_relocation(mac_client_impl_t *,
 929     boolean_t);
 930 
 931 /* Global callbacks into the bridging module (when loaded) */
 932 extern mac_bridge_tx_t mac_bridge_tx_cb;
 933 extern mac_bridge_rx_t mac_bridge_rx_cb;
 934 extern mac_bridge_ref_t mac_bridge_ref_cb;
 935 extern mac_bridge_ls_t mac_bridge_ls_cb;
 936 
 937 /*
 938  * MAC Transceiver related functions
 939  */
 940 struct mac_transceiver_info {
 941         boolean_t               mti_present;
 942         boolean_t               mti_usable;
 943 };
 944 
 945 extern void mac_transceiver_init(mac_impl_t *);
 946 extern int mac_transceiver_count(mac_handle_t, uint_t *);
 947 extern int mac_transceiver_info(mac_handle_t, uint_t, boolean_t *, boolean_t *);
 948 extern int mac_transceiver_read(mac_handle_t, uint_t, uint_t, void *, size_t,
 949     off_t, size_t *);
 950 
 951 /*
 952  * MAC LED related functions
 953  */
 954 #define MAC_LED_ALL     (MAC_LED_DEFAULT | MAC_LED_OFF | MAC_LED_IDENT | \
 955                             MAC_LED_ON)
 956 extern void mac_led_init(mac_impl_t *);
 957 extern int mac_led_get(mac_handle_t, mac_led_mode_t *, mac_led_mode_t *);
 958 extern int mac_led_set(mac_handle_t, mac_led_mode_t);
 959 
 960 #ifdef  __cplusplus
 961 }
 962 #endif
 963 
 964 #endif  /* _SYS_MAC_IMPL_H */