mac_impl.h revision 0591ddd0694c4d7ab3ad339419da215a732587f8
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
#ifndef _SYS_MAC_IMPL_H
#define _SYS_MAC_IMPL_H
#include <sys/mac_client.h>
#include <sys/mac_provider.h>
#include <sys/mac_flow_impl.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* This is the first minor number available for MAC provider private
* use. This makes it possible to deliver a driver that is both a MAC
* for more detail about the construction of such devices. The value
* chosen leaves half of the 32-bit minor numbers (which are really
* only 18 bits wide) available for driver private use. Drivers can
* easily identify their private number by the presence of this value
* in the bits that make up the minor number, since its just the
* highest bit available for such minor numbers.
*/
/*
* The maximum minor number that corresponds to a real instance. This
* limits the number of physical ports that a mac provider can offer.
* Note that this macro must be synchronized with DLS_MAX_MINOR in
*/
#define MAC_MAX_MINOR 1000
typedef struct mac_margin_req_s mac_margin_req_t;
struct mac_margin_req_s {
};
/* Generic linked chain type */
typedef struct mac_chain_s {
struct mac_chain_s *next;
void *item;
} mac_chain_t;
/*
* Generic mac callback list manipulation structures and macros. The mac_cb_t
* represents a general callback list element embedded in a particular
* data structure such as a mac_notify_cb_t or a mac_promisc_impl_t.
* The mac_cb_info_t represents general information about list walkers.
* Please see the comments above mac_callback_add for more information.
*/
/* mcb_flags */
#define MCB_NOTIFY_CB_T 0x2
#define MCB_TX_NOTIFY_CB_T 0x4
extern boolean_t mac_tx_serialize;
typedef struct mac_cb_s {
void *mcb_objp; /* Ptr to enclosing object */
} mac_cb_t;
typedef struct mac_cb_info_s {
typedef struct mac_notify_cb_s {
void *mncb_arg; /* callback argument */
struct mac_impl_s *mncb_mip;
/*
* mac_callback_add(listinfo, listhead, listelement)
* mac_callback_remove(listinfo, listhead, listelement)
*/
#define MAC_CALLBACK_WALKER_INC(mcbi) { \
(mcbi)->mcbi_walker_cnt++; \
}
\
} \
}
#define MAC_PROMISC_WALKER_INC(mip) \
#define MAC_PROMISC_WALKER_DCR(mip) { \
mac_cb_info_t *mcbi; \
\
} \
}
typedef struct mactype_s {
const char *mt_ident;
} mactype_t;
/*
* Multiple rings implementation.
*/
typedef enum {
MAC_GROUP_STATE_UNINIT = 0, /* initial state of data structure */
MAC_GROUP_STATE_REGISTERED, /* hooked with h/w group */
MAC_GROUP_STATE_RESERVED, /* group is reserved and opened */
MAC_GROUP_STATE_SHARED /* default group shared among */
/* multiple mac clients */
typedef struct mac_ring_s mac_ring_t;
typedef struct mac_group_s mac_group_t;
/*
* Ring data structure for ring control and management.
*/
typedef enum {
MR_FREE, /* Available for assignment to flows */
MR_NEWLY_ADDED, /* Just assigned to another group */
MR_INUSE /* Assigned to an SRS */
/* mr_flag values */
#define MR_INCIPIENT 0x1
#define MR_CONDEMNED 0x2
#define MR_QUIESCE 0x4
typedef struct mac_impl_s mac_impl_t;
struct mac_ring_s {
int mr_index; /* index in the original list */
/* ring generation no. to guard against drivers using stale rings */
};
/*
* Reference hold and release on mac_ring_t 'mr'
*/
#define MR_REFHOLD_LOCKED(mr) { \
}
#define MR_REFRELE(mr) { \
}
/*
* Per mac client flow information associated with a RX group.
* The entire structure is SL protected.
*/
typedef struct mac_grp_client {
struct mac_grp_client *mgc_next;
struct mac_client_impl_s *mgc_client;
#define MAC_GROUP_ONLY_CLIENT(g) \
((((g)->mrg_clients != NULL) && \
/*
* Common ring group data structure for ring control and management.
* The entire structure is SL protected
*/
struct mac_group_s {
int mrg_index; /* index in the list */
};
/* \
* Send packets through a selected tx ring, or through the \
* default handler if there is no selected ring. \
*/ \
} else { \
} \
}
/*
* This is the final stop before reaching the underlying driver
* or aggregation, so this is where the bridging hook is implemented.
* Packets that are bridged will return through mac_bridge_tx(), with
* rh nulled out if the bridge chooses to send output on a different
* link due to forwarding.
*/
/* \
* If there is a bound Hybrid I/O share, send packets through \
* the default tx ring. (When there's a bound Hybrid I/O share, \
* the tx rings of this client are mapped in the guest domain \
* and not accessible from here.) \
*/ \
/* \
* Grab the proper transmit pointer and handle. Special \
* optimization: we can test mi_bridge_link itself atomically, \
* and if that indicates no bridge send packets through tx ring.\
*/ \
} else { \
} \
}
/* mci_tx_flag */
#define MCI_TX_QUIESCE 0x1
typedef struct mac_factory_addr_s {
struct mac_client_impl_s *mfa_client;
typedef struct mac_mcast_addrs_s {
struct mac_mcast_addrs_s *mma_next;
int mma_ref;
typedef enum {
MAC_ADDRESS_TYPE_UNICAST_PROMISC /* promiscuous mode */
typedef struct mac_address_s {
int ma_nusers; /* number of users */
/* of that address */
extern krwlock_t i_mac_impl_lock;
extern mod_hash_t *i_mac_impl_hash;
extern kmem_cache_t *i_mac_impl_cachep;
extern uint_t i_mac_impl_count;
/*
* Each registered MAC is associated with a mac_impl_t structure. The
* structure represents the undelying hardware, in terms of definition,
* resources (transmit, receive rings etc.), callback functions etc. It
* also holds the table of MAC clients that are configured on the device.
* The table is used for classifying incoming packets in software.
*
* The protection scheme uses 2 elements, a coarse serialization mechanism
* called perimeter and a finer traditional lock based scheme. More details
* can be found in the big block comment in mac.c.
*
* The protection scheme for each member of the mac_impl_t is described below.
*
* Write Once Only (WO): Typically these don't change for the lifetime of the
* data structure. For example something in mac_impl_t that stays the same
* from mac_register to mac_unregister, or something in a mac_client_impl_t
* that stays the same from mac_client_open to mac_client_close.
*
* Serializer (SL): Protected by the Serializer. All SLOP operations on a
* mac endpoint go through the serializer. MTOPs don't care about reading
* these fields atomically.
*
* mac serializer, the lock helps synchronize readers with writers.
*/
struct mac_impl_s {
void *mi_driver; /* Driver private, WO */
void *mi_pdata; /* WO */
/*
* on a mac end point go through this.
*/
/* mac notification callbacks */
/*
* RX groups, ring capability
* Fields of this block are SL protected.
*/
/*
* TX groups and ring capability, SL Protected.
*/
/*
* MAC address list. SL protected.
*/
/*
* This MAC's table of sub-flows
*/
/* for broadcast and multicast support */
/* list of MAC clients which opened this MAC */
/*
* Cache of factory MAC addresses provided by the driver. If
* the driver doesn't provide multiple factory MAC addresses,
* the mi_factory_addr is set to NULL, and mi_factory_addr_num
* is set to zero.
*/
/* for promiscuous mode support */
/* cache of rings over this mac_impl */
/*
* These are used for caching the properties, if any, for the
* primary MAC client. If the MAC client is not yet in place
* when the properties are set then we cache them here to be
* applied to the MAC client when it is created.
*/
/*
* List of margin value requests added by mac clients. This list is
* sorted: the first one has the greatest value.
*/
char **mi_priv_prop;
/*
* Hybrid I/O related definitions.
*/
/*
* Bridging hooks and limit values. Uses mutex and reference counts
* (bridging only) for data path. Limits need no synchronization.
*/
/* This should be the last block in this structure */
#ifdef DEBUG
#define MAC_PERIM_STACK_DEPTH 15
int mi_perim_stack_depth;
#endif
};
/*
* The default TX group is the last one in the list.
*/
#define MAC_DEFAULT_TX_GROUP(mip) \
/*
* The default RX group is the first one in the list
*/
/* Reserved RX rings */
#define MAC_RX_RING_RESERVED(m, cnt) { \
(m)->mi_rxrings_rsvd += (cnt); \
(m)->mi_rxrings_avail -= (cnt); \
}
/* Released RX rings */
#define MAC_RX_RING_RELEASED(m, cnt) { \
(m)->mi_rxrings_rsvd -= (cnt); \
(m)->mi_rxrings_avail += (cnt); \
}
/* Reserved a RX group */
#define MAC_RX_GRP_RESERVED(m) { \
ASSERT((m)->mi_rxhwclnt_avail > 0); \
(m)->mi_rxhwclnt_avail--; \
(m)->mi_rxhwclnt_used++; \
}
/* Released a RX group */
#define MAC_RX_GRP_RELEASED(m) { \
ASSERT((m)->mi_rxhwclnt_used > 0); \
(m)->mi_rxhwclnt_avail++; \
(m)->mi_rxhwclnt_used--; \
}
/* Reserved TX rings */
#define MAC_TX_RING_RESERVED(m, cnt) { \
(m)->mi_txrings_rsvd += (cnt); \
(m)->mi_txrings_avail -= (cnt); \
}
/* Released TX rings */
#define MAC_TX_RING_RELEASED(m, cnt) { \
(m)->mi_txrings_rsvd -= (cnt); \
(m)->mi_txrings_avail += (cnt); \
}
/* Reserved a TX group */
#define MAC_TX_GRP_RESERVED(m) { \
ASSERT((m)->mi_txhwclnt_avail > 0); \
(m)->mi_txhwclnt_avail--; \
(m)->mi_txhwclnt_used++; \
}
/* Released a TX group */
#define MAC_TX_GRP_RELEASED(m) { \
ASSERT((m)->mi_txhwclnt_used > 0); \
(m)->mi_txhwclnt_avail++; \
(m)->mi_txhwclnt_used--; \
}
/* for mi_state_flags */
#define MIS_DISABLED 0x0001
#define MIS_IS_VNIC 0x0002
#define MIS_IS_AGGR 0x0004
#define MIS_NOTIFY_DONE 0x0008
#define MIS_EXCLUSIVE 0x0010
#define MIS_EXCLUSIVE_HELD 0x0020
#define MIS_LEGACY 0x0040
#define MIS_NO_ACTIVE 0x0080
#define MIS_POLL_DISABLE 0x0100
typedef struct mac_notify_task_arg {
/*
* XXX All MAC_DBG_PRTs must be replaced with call to dtrace probes. For now
* it may be easier to have these printfs for easier debugging
*/
#ifdef DEBUG
extern int mac_dbg;
#else
#define MAC_DBG_PRT(a)
#endif
/*
* The mac_perim_handle_t is an opaque type that encodes the 'mip' pointer
* and whether internally a mac_open was done when acquiring the perimeter.
*/
}
/*
* Type of property information that can be returned by a driver.
* Valid flags of the pr_flags of the mac_prop_info_t data structure.
*/
#define MAC_PROP_INFO_DEFAULT 0x0001
#define MAC_PROP_INFO_RANGE 0x0002
#define MAC_PROP_INFO_PERM 0x0004
/*
* Property information. pr_flags is a combination of one of the
* MAC_PROP_INFO_* flags, it is reset by the framework before invoking
* the driver's prefix_propinfo() entry point.
*
* Drivers should use MAC_PROP_INFO_SET_*() macros to provide
* information about a property.
*/
typedef struct mac_prop_info_state_s {
void *pr_default;
typedef struct mac_client_impl_s mac_client_impl_t;
extern void mac_init(void);
extern int mac_fini(void);
uint8_t *, ip6_frag_t **);
extern void mac_tx_notify(mac_impl_t *);
extern void mac_callback_remove_wait(mac_cb_info_t *);
extern void mac_callback_free(mac_cb_t *);
/* in mac_bcast.c */
extern void mac_bcast_init(void);
extern void mac_bcast_fini(void);
extern mac_impl_t *mac_bcast_grp_mip(void *);
extern void mac_bcast_grp_free(void *);
void *, boolean_t);
/*
* Grouping functions are used internally by MAC layer.
*/
mac_group_t *);
mac_group_t *);
mac_group_t *);
extern void mac_rx_switch_grp_to_sw(mac_group_t *);
/*
* MAC address functions are used internally by MAC layer.
*/
extern void mac_init_macaddr(mac_impl_t *);
extern void mac_fini_macaddr(mac_impl_t *);
/*
* Flow construction/destruction routines.
* Not meant to be used by mac clients.
*/
/*
* Fanout update routines called when the link speed of the NIC changes
* or when a MAC client's share is unbound.
*/
extern void mac_fanout_recompute(mac_impl_t *);
/*
* The following functions are used internally by the MAC layer to
* never be used directly by MAC clients.
*/
uint32_t);
uint32_t);
uint32_t);
uint32_t);
extern int mac_rx_classify_flow_quiesce(flow_entry_t *, void *);
extern int mac_rx_classify_flow_restart(flow_entry_t *, void *);
extern void mac_client_quiesce(mac_client_impl_t *);
extern void mac_client_restart(mac_client_impl_t *);
extern void mac_flow_rem_subflow(flow_entry_t *);
extern void mac_rename_flow(flow_entry_t *, const char *);
extern void mac_flow_set_name(flow_entry_t *, const char *);
extern void i_mac_share_alloc(mac_client_impl_t *);
extern void i_mac_share_free(mac_client_impl_t *);
extern void i_mac_perim_enter(mac_impl_t *);
extern void i_mac_perim_exit(mac_impl_t *);
extern int i_mac_perim_enter_nowait(mac_impl_t *);
extern int mac_hold(const char *, mac_impl_t **);
extern void mac_rele(mac_impl_t *);
extern int i_mac_disable(mac_impl_t *);
extern void i_mac_notify_exit(mac_impl_t *);
extern void mac_tx_client_flush(mac_client_impl_t *);
extern void mac_tx_client_block(mac_client_impl_t *);
extern void mac_tx_client_unblock(mac_client_impl_t *);
extern void i_mac_promisc_walker_cleanup(mac_impl_t *);
extern mactype_t *mactype_getplugin(const char *);
extern void mac_addr_factory_init(mac_impl_t *);
extern void mac_addr_factory_fini(mac_impl_t *);
extern void mac_register_priv_prop(mac_impl_t *, char **);
extern void mac_unregister_priv_prop(mac_impl_t *);
extern int mac_start_group(mac_group_t *);
extern void mac_stop_group(mac_group_t *);
extern int mac_start_ring(mac_ring_t *);
extern void mac_stop_ring(mac_ring_t *);
extern int mac_remove_macaddr(mac_address_t *);
mac_group_t *);
extern int mac_protect_validate(mac_resource_props_t *);
extern void mac_protect_update_v6_local_addr(mac_client_impl_t *);
extern void mac_protect_flush_dhcp(mac_client_impl_t *);
extern void mac_protect_cancel_timer(mac_client_impl_t *);
extern void mac_protect_init(mac_client_impl_t *);
extern void mac_protect_fini(mac_client_impl_t *);
extern void mac_set_rings_effective(mac_client_impl_t *);
/* Global callbacks into the bridging module (when loaded) */
extern mac_bridge_tx_t mac_bridge_tx_cb;
extern mac_bridge_rx_t mac_bridge_rx_cb;
extern mac_bridge_ref_t mac_bridge_ref_cb;
extern mac_bridge_ls_t mac_bridge_ls_cb;
#ifdef __cplusplus
}
#endif
#endif /* _SYS_MAC_IMPL_H */