#ifndef _SYS_MAC_CLIENT_IMPL_H
#define _SYS_MAC_CLIENT_IMPL_H
#include <sys/modhash.h>
#include <sys/mac_client.h>
#include <sys/mac_provider.h>
#include <sys/mac.h>
#include <sys/mac_impl.h>
#include <sys/mac_stat.h>
#include <net/if.h>
#include <sys/mac_flow_impl.h>
#ifdef __cplusplus
extern "C" {
#endif
extern kmem_cache_t *mac_client_impl_cache;
extern kmem_cache_t *mac_unicast_impl_cache;
extern kmem_cache_t *mac_promisc_impl_cache;
typedef struct mac_unicast_impl_s {
struct mac_unicast_impl_s *mui_next;
mac_address_t *mui_map;
uint16_t mui_vid;
} mac_unicast_impl_t;
typedef struct mac_promisc_impl_s {
mac_cb_t mpi_mci_link;
mac_cb_t mpi_mi_link;
mac_client_promisc_type_t mpi_type;
mac_rx_t mpi_fn;
void *mpi_arg;
struct mac_client_impl_s *mpi_mcip;
boolean_t mpi_no_tx_loop;
boolean_t mpi_no_phys;
boolean_t mpi_strip_vlan_tag;
boolean_t mpi_no_copy;
boolean_t mpi_rx_only;
boolean_t mpi_tx_only;
} mac_promisc_impl_t;
typedef union mac_tx_percpu_s {
struct {
kmutex_t _pcpu_tx_lock;
uint_t _pcpu_tx_refcnt;
} pcpu_lr;
uchar_t pcpu_pad[64];
} mac_tx_percpu_t;
#define pcpu_tx_lock pcpu_lr._pcpu_tx_lock
#define pcpu_tx_refcnt pcpu_lr._pcpu_tx_refcnt
typedef enum {
MAC_CLIENT_FLAGS_PRIMARY = 1 << 0,
MAC_CLIENT_FLAGS_VNIC_PRIMARY = 1 << 1,
MAC_CLIENT_FLAGS_MULTI_PRIMARY = 1 << 2,
MAC_CLIENT_FLAGS_PASSIVE_PRIMARY = 1 << 3,
} mac_client_flags_t;
typedef enum {
MCIS_IS_VNIC = 1 << 0,
MCIS_EXCLUSIVE = 1 << 1,
MCIS_TAG_DISABLE = 1 << 2,
MCIS_STRIP_DISABLE = 1 << 3,
MCIS_IS_AGGR_PORT = 1 << 4,
MCIS_CLIENT_POLL_CAPABLE = 1 << 5,
MCIS_DESC_LOGGED = 1 << 6,
MCIS_SHARE_BOUND = 1 << 7,
MCIS_DISABLE_TX_VID_CHECK = 1 << 8,
MCIS_USE_DATALINK_NAME = 1 << 9,
MCIS_UNICAST_HW = 1 << 10,
MCIS_IS_AGGR_CLIENT = 1 << 11,
MCIS_RX_BYPASS_DISABLE = 1 << 12,
MCIS_NO_UNICAST_ADDR = 1 << 13,
} mac_client_state_t;
struct mac_client_impl_s {
struct mac_client_impl_s *mci_client_next;
char mci_name[MAXNAMELEN];
flow_entry_t *mci_flent;
struct mac_impl_s *mci_mip;
struct mac_impl_s *mci_upper_mip;
mac_client_state_t mci_state_flags;
mac_rx_t mci_rx_fn;
void *mci_rx_arg;
mac_direct_rxs_t mci_direct_rx;
mac_rx_t mci_rx_p_fn;
void *mci_rx_p_arg;
void *mci_p_unicast_list;
mac_cb_t *mci_promisc_list;
mac_address_t *mci_unicast;
mac_client_flags_t mci_flags;
krwlock_t mci_rw_lock;
mac_unicast_impl_t *mci_unicast_list;
flow_entry_t *mci_flent_list;
uint_t mci_nflents;
uint_t mci_nvids;
volatile uint32_t mci_vidcache;
mac_resource_cb_t mci_rcb4;
mac_resource_cb_t mci_rcb6;
kmutex_t mci_tx_cb_lock;
mac_cb_info_t mci_tx_notify_cb_info;
mac_cb_t *mci_tx_notify_cb_list;
uintptr_t mci_tx_notify_id;
mac_misc_stats_t mci_misc_stat;
flow_tab_t *mci_subflow_tab;
pri_t mci_min_pri;
pri_t mci_max_pri;
mac_share_handle_t mci_share;
struct mac_mcast_addrs_s *mci_mcast_addrs;
kmutex_t mci_protect_lock;
uint32_t mci_protect_flags;
in6_addr_t mci_v6_mac_token;
in6_addr_t mci_v6_local_addr;
avl_tree_t mci_v4_pending_txn;
avl_tree_t mci_v4_completed_txn;
avl_tree_t mci_v4_dyn_ip;
avl_tree_t mci_v6_pending_txn;
avl_tree_t mci_v6_cid;
avl_tree_t mci_v6_dyn_ip;
avl_tree_t mci_v6_slaac_ip;
timeout_id_t mci_txn_cleanup_tid;
uint_t mci_tx_flag;
kcondvar_t mci_tx_cv;
mac_tx_percpu_t mci_tx_pcpu[1];
};
#define MAC_CLIENT_IMPL_SIZE \
(sizeof (mac_client_impl_t) + \
(mac_tx_percpu_cnt * sizeof (mac_tx_percpu_t)))
extern int mac_tx_percpu_cnt;
#define MCIP_TX_SRS(mcip) \
((mcip)->mci_flent == NULL ? NULL : (mcip)->mci_flent->fe_tx_srs)
#define MCIP_DATAPATH_SETUP(mcip) \
((mcip)->mci_flent == NULL ? B_FALSE : \
!((mcip)->mci_flent->fe_flags & FE_MC_NO_DATAPATH))
#define MCIP_RESOURCE_PROPS(mcip) \
((mcip)->mci_flent == NULL ? NULL : \
&(mcip)->mci_flent->fe_resource_props)
#define MCIP_EFFECTIVE_PROPS(mcip) \
(mcip->mci_flent == NULL ? NULL : \
&(mcip)->mci_flent->fe_effective_props)
#define MCIP_RESOURCE_PROPS_MASK(mcip) \
((mcip)->mci_flent == NULL ? 0 : \
(mcip)->mci_flent->fe_resource_props.mrp_mask)
#define MCIP_RESOURCE_PROPS_MAXBW(mcip) \
((mcip)->mci_flent == NULL ? 0 : \
(mcip)->mci_flent->fe_resource_props.mrp_maxbw)
#define MCIP_RESOURCE_PROPS_PRIORITY(mcip) \
((mcip)->mci_flent == NULL ? 0 : \
(mcip)->mci_flent->fe_resource_props.mrp_priority)
#define MCIP_RESOURCE_PROPS_CPUS(mcip) \
((mcip)->mci_flent == NULL ? 0 : \
&(mcip)->mci_flent->fe_resource_props.mrp_cpus)
#define MCIP_RESOURCE_PROPS_NCPUS(mcip) \
((mcip)->mci_flent == NULL ? 0 : \
(mcip)->mci_flent->fe_resource_props.mrp_ncpus)
#define MCIP_RESOURCE_PROPS_CPU(mcip) \
((mcip)->mci_flent == NULL ? 0 : \
(mcip)->mci_flent->fe_resource_props.mrp_ncpu)
#define MAC_VID_CHECK_NEEDED(mcip) \
(((mcip)->mci_state_flags & MCIS_DISABLE_TX_VID_CHECK) == 0 && \
(mcip)->mci_mip->mi_info.mi_nativemedia == DL_ETHER)
#define MAC_VID_CHECK(mcip, mp, err) { \
if (ntohs(((struct ether_header *)(mp)->b_rptr)->ether_type) == \
ETHERTYPE_VLAN) { \
\
(err) = EINVAL; \
if (((mcip)->mci_state_flags & MCIS_TAG_DISABLE) != 0) {\
struct ether_vlan_header *evhp; \
uint16_t vlanid; \
\
evhp = (struct ether_vlan_header *)(mp)->b_rptr;\
vlanid = VLAN_ID(ntohs(evhp->ether_tci)); \
if (mac_client_check_flow_vid((mcip), vlanid)) \
(err) = 0; \
} \
} \
}
#define MCIP_VIDCACHE_VALIDSHIFT 31
#define MCIP_VIDCACHE_VIDSHIFT 1
#define MCIP_VIDCACHE_VIDMASK (UINT16_MAX << MCIP_VIDCACHE_VIDSHIFT)
#define MCIP_VIDCACHE_BOOLSHIFT 0
#define MCIP_VIDCACHE_INVALID 0
#define MCIP_VIDCACHE_CACHE(vid, bool) \
((1U << MCIP_VIDCACHE_VALIDSHIFT) | \
((vid) << MCIP_VIDCACHE_VIDSHIFT) | \
((bool) ? (1U << MCIP_VIDCACHE_BOOLSHIFT) : 0))
#define MCIP_VIDCACHE_ISVALID(v) ((v) & (1U << MCIP_VIDCACHE_VALIDSHIFT))
#define MCIP_VIDCACHE_VID(v) \
(((v) & MCIP_VIDCACHE_VIDMASK) >> MCIP_VIDCACHE_VIDSHIFT)
#define MCIP_VIDCACHE_BOOL(v) ((v) & (1U << MCIP_VIDCACHE_BOOLSHIFT))
#define MAC_TAG_NEEDED(mcip) \
(((mcip)->mci_state_flags & MCIS_TAG_DISABLE) == 0 && \
(mcip)->mci_nvids == 1) \
#define MPT_FLAG_V6_LOCAL_ADDR_SET 0x0001
#define MPT_FLAG_PROMISC_FILTERED 0x0002
extern void mac_promisc_client_dispatch(mac_client_impl_t *, mblk_t *);
extern void mac_client_init(void);
extern void mac_client_fini(void);
extern void mac_promisc_dispatch(mac_impl_t *, mblk_t *, mac_client_impl_t *,
boolean_t);
extern int mac_validate_props(mac_impl_t *, mac_resource_props_t *);
extern mac_client_impl_t *mac_vnic_lower(mac_impl_t *);
extern mac_client_impl_t *mac_primary_client_handle(mac_impl_t *);
extern uint16_t i_mac_flow_vid(flow_entry_t *);
extern boolean_t i_mac_capab_get(mac_handle_t, mac_capab_t, void *);
extern void mac_unicast_update_clients(mac_impl_t *, mac_address_t *);
extern void mac_update_resources(mac_resource_props_t *,
mac_resource_props_t *, boolean_t);
boolean_t mac_client_check_flow_vid(mac_client_impl_t *, uint16_t);
extern boolean_t mac_is_primary_client(mac_client_impl_t *);
extern int mac_client_set_rings_prop(mac_client_impl_t *,
mac_resource_props_t *, mac_resource_props_t *);
extern void mac_set_prim_vlan_rings(mac_impl_t *, mac_resource_props_t *);
#ifdef __cplusplus
}
#endif
#endif