xref: /onnv-gate/usr/src/uts/common/sys/mac_flow_impl.h (revision 11878:ac93462db6d7)
18275SEric Cheng /*
28275SEric Cheng  * CDDL HEADER START
38275SEric Cheng  *
48275SEric Cheng  * The contents of this file are subject to the terms of the
58275SEric Cheng  * Common Development and Distribution License (the "License").
68275SEric Cheng  * You may not use this file except in compliance with the License.
78275SEric Cheng  *
88275SEric Cheng  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
98275SEric Cheng  * or http://www.opensolaris.org/os/licensing.
108275SEric Cheng  * See the License for the specific language governing permissions
118275SEric Cheng  * and limitations under the License.
128275SEric Cheng  *
138275SEric Cheng  * When distributing Covered Code, include this CDDL HEADER in each
148275SEric Cheng  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
158275SEric Cheng  * If applicable, add the following below this CDDL HEADER, with the
168275SEric Cheng  * fields enclosed by brackets "[]" replaced with your own identifying
178275SEric Cheng  * information: Portions Copyright [yyyy] [name of copyright owner]
188275SEric Cheng  *
198275SEric Cheng  * CDDL HEADER END
208275SEric Cheng  */
218275SEric Cheng 
228275SEric Cheng /*
23*11878SVenu.Iyer@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
248275SEric Cheng  * Use is subject to license terms.
258275SEric Cheng  */
268275SEric Cheng 
278275SEric Cheng #ifndef	_MAC_FLOW_IMPL_H
288275SEric Cheng #define	_MAC_FLOW_IMPL_H
298275SEric Cheng 
308275SEric Cheng #ifdef	__cplusplus
318275SEric Cheng extern "C" {
328275SEric Cheng #endif
338275SEric Cheng 
348275SEric Cheng #include <sys/param.h>
358275SEric Cheng #include <sys/atomic.h>
368275SEric Cheng #include <sys/ksynch.h>
378275SEric Cheng #include <sys/mac_flow.h>
388275SEric Cheng #include <sys/stream.h>
398275SEric Cheng #include <sys/sdt.h>
408275SEric Cheng #include <net/if.h>
418275SEric Cheng 
428275SEric Cheng /*
438275SEric Cheng  * Macros to increment/decrement the reference count on a flow_entry_t.
448275SEric Cheng  */
458275SEric Cheng #define	FLOW_REFHOLD(flent) {					\
468275SEric Cheng 	DTRACE_PROBE1(flow_refhold, flow_entry_t *, (flent));	\
478275SEric Cheng 	mutex_enter(&(flent)->fe_lock);				\
488275SEric Cheng 	(flent)->fe_refcnt++;					\
498275SEric Cheng 	mutex_exit(&(flent)->fe_lock);				\
508275SEric Cheng }
518275SEric Cheng 
528275SEric Cheng /*
538275SEric Cheng  * Data paths must not attempt to use a flow entry if it is marked INCIPIENT
548275SEric Cheng  * or QUIESCE. In the former case the set up is not yet complete and the
558275SEric Cheng  * data path could stumble on inconsistent data structures. In the latter
568275SEric Cheng  * case a control operation is waiting for quiescence so that it can
578275SEric Cheng  * change callbacks or other structures without the use of locks.
588275SEric Cheng  */
598275SEric Cheng #define	FLOW_TRY_REFHOLD(flent, err) {				\
608275SEric Cheng 	DTRACE_PROBE1(flow_refhold, flow_entry_t *, (flent));	\
618275SEric Cheng 	(err) = 0;						\
628275SEric Cheng 	mutex_enter(&(flent)->fe_lock);				\
638275SEric Cheng 	if ((flent)->fe_flags & (FE_INCIPIENT | FE_QUIESCE | FE_CONDEMNED | \
648275SEric Cheng 	    FE_UF_NO_DATAPATH | FE_MC_NO_DATAPATH))			\
658275SEric Cheng 		(err) = -1;					\
668275SEric Cheng 	else							\
678275SEric Cheng 		(flent)->fe_refcnt++;				\
688275SEric Cheng 	mutex_exit(&(flent)->fe_lock);				\
698275SEric Cheng }
708275SEric Cheng 
718275SEric Cheng #define	FLOW_REFRELE(flent) {					\
728275SEric Cheng 	DTRACE_PROBE1(flow_refrele, flow_entry_t *, (flent));	\
738275SEric Cheng 	mutex_enter(&(flent)->fe_lock);				\
748275SEric Cheng 	ASSERT((flent)->fe_refcnt != 0);			\
758275SEric Cheng 	(flent)->fe_refcnt--;					\
768275SEric Cheng 	if ((flent)->fe_flags & FE_WAITER) {			\
778275SEric Cheng 		ASSERT((flent)->fe_refcnt != 0);		\
788275SEric Cheng 		cv_signal(&(flent)->fe_cv);			\
798275SEric Cheng 		mutex_exit(&(flent)->fe_lock);			\
808275SEric Cheng 	} else if ((flent)->fe_refcnt == 0) {			\
818275SEric Cheng 		mac_flow_destroy(flent);			\
828275SEric Cheng 	} else {						\
838275SEric Cheng 		mutex_exit(&(flent)->fe_lock);			\
848275SEric Cheng 	}							\
858275SEric Cheng }
868275SEric Cheng 
878275SEric Cheng #define	FLOW_USER_REFHOLD(flent) {			\
888275SEric Cheng 	mutex_enter(&(flent)->fe_lock);			\
898275SEric Cheng 	(flent)->fe_user_refcnt++;			\
908275SEric Cheng 	mutex_exit(&(flent)->fe_lock);			\
918275SEric Cheng }
928275SEric Cheng 
938275SEric Cheng #define	FLOW_USER_REFRELE(flent) {			\
948275SEric Cheng 	mutex_enter(&(flent)->fe_lock);			\
958275SEric Cheng 	ASSERT((flent)->fe_user_refcnt != 0);		\
968275SEric Cheng 	if (--(flent)->fe_user_refcnt == 0 &&		\
978275SEric Cheng 	    ((flent)->fe_flags & FE_WAITER))		\
988275SEric Cheng 		cv_signal(&(flent)->fe_cv);		\
998275SEric Cheng 	mutex_exit(&(flent)->fe_lock);			\
1008275SEric Cheng }
1018275SEric Cheng 
1028275SEric Cheng #define	FLOW_FINAL_REFRELE(flent) {			\
1038275SEric Cheng 	ASSERT(flent->fe_refcnt == 1 && flent->fe_user_refcnt == 0);	\
1048275SEric Cheng 	FLOW_REFRELE(flent);				\
1058275SEric Cheng }
1068275SEric Cheng 
1078275SEric Cheng /*
1088275SEric Cheng  * Mark or unmark the flent with a bit flag
1098275SEric Cheng  */
1108275SEric Cheng #define	FLOW_MARK(flent, flag) {		\
1118275SEric Cheng 	mutex_enter(&(flent)->fe_lock);		\
1128275SEric Cheng 	(flent)->fe_flags |= flag;		\
1138275SEric Cheng 	mutex_exit(&(flent)->fe_lock);		\
1148275SEric Cheng }
1158275SEric Cheng 
1168275SEric Cheng #define	FLOW_UNMARK(flent, flag) {		\
1178275SEric Cheng 	mutex_enter(&(flent)->fe_lock);		\
1188275SEric Cheng 	(flent)->fe_flags &= ~flag;		\
1198275SEric Cheng 	mutex_exit(&(flent)->fe_lock);		\
1208275SEric Cheng }
1218275SEric Cheng 
1228275SEric Cheng #define	FLENT_TO_MIP(flent)			\
1238275SEric Cheng 	(flent->fe_mbg != NULL ? mac_bcast_grp_mip(flent->fe_mbg) :	\
1248275SEric Cheng 	((mac_client_impl_t *)flent->fe_mcip)->mci_mip)
1258275SEric Cheng 
1268275SEric Cheng /* Convert a bandwidth expressed in bps to a number of bytes per tick. */
1278275SEric Cheng #define	FLOW_BYTES_PER_TICK(bps)	(((bps) >> 3) / hz)
1288275SEric Cheng 
1298275SEric Cheng /*
1308275SEric Cheng  * Given an underlying range and a priority level, obtain the minimum for the
1318275SEric Cheng  * new range.
1328275SEric Cheng  */
1338275SEric Cheng #define	FLOW_MIN_PRIORITY(min, max, pri)	\
1348275SEric Cheng 	((min) + ((((max) - (min)) / MRP_PRIORITY_LEVELS) * (pri)))
1358275SEric Cheng 
1368275SEric Cheng /*
1378275SEric Cheng  * Given an underlying range and a minimum level (base), obtain the maximum
1388275SEric Cheng  * for the new range.
1398275SEric Cheng  */
1408275SEric Cheng #define	FLOW_MAX_PRIORITY(min, max, base)	\
1418275SEric Cheng 	((base) + (((max) - (min)) / MRP_PRIORITY_LEVELS))
1428275SEric Cheng 
1438275SEric Cheng /*
1448275SEric Cheng  * Given an underlying range and a priority level, get the absolute
1458275SEric Cheng  * priority value. For now there are just 3 values, high, low and
1468275SEric Cheng  * medium  so we can just return max, min or min + (max - min) / 2.
1478275SEric Cheng  * If there are more than three we need to change this computation.
1488275SEric Cheng  */
1498275SEric Cheng #define	FLOW_PRIORITY(min, max, pri)		\
1508275SEric Cheng 	(pri) == MPL_HIGH ? (max) :	\
1518275SEric Cheng 	(pri) == MPL_LOW ? (min) :	\
1528275SEric Cheng 	((min) + (((max) - (min)) / 2))
1538275SEric Cheng 
1548275SEric Cheng #define	MAC_FLOW_TAB_SIZE		500
1558275SEric Cheng 
1568275SEric Cheng typedef struct flow_entry_s		flow_entry_t;
1578275SEric Cheng typedef struct flow_tab_s		flow_tab_t;
1588275SEric Cheng typedef struct flow_state_s 		flow_state_t;
1598275SEric Cheng struct mac_impl_s;
1608275SEric Cheng struct mac_client_impl_s;
1618275SEric Cheng 
1628275SEric Cheng /*
1638275SEric Cheng  * Classification flags used to lookup the flow.
1648275SEric Cheng  */
1658275SEric Cheng #define	FLOW_INBOUND		0x01
1668275SEric Cheng #define	FLOW_OUTBOUND		0x02
1678275SEric Cheng /* Don't compare VID when classifying the packets, see mac_rx_classify() */
1688275SEric Cheng #define	FLOW_IGNORE_VLAN	0x04
1698275SEric Cheng 
1708275SEric Cheng /* Generic flow client function signature */
1718275SEric Cheng typedef void		(*flow_fn_t)(void *, void *, mblk_t *, boolean_t);
1728275SEric Cheng 
1738275SEric Cheng /* Flow state */
1748275SEric Cheng typedef enum {
1758275SEric Cheng 	FLOW_DRIVER_UPCALL,
1768275SEric Cheng 	FLOW_USER_REF
1778275SEric Cheng } mac_flow_state_t;
1788275SEric Cheng 
1798275SEric Cheng /* Matches a flow_entry_t using the extracted flow_state_t info */
1808275SEric Cheng typedef boolean_t	(*flow_match_fn_t)(flow_tab_t *, flow_entry_t *,
1818275SEric Cheng 			    flow_state_t *);
1828275SEric Cheng 
1838275SEric Cheng /* fe_flags */
1848275SEric Cheng #define	FE_QUIESCE		0x01	/* Quiesce the flow */
1858275SEric Cheng #define	FE_WAITER		0x02	/* Flow has a waiter */
1868275SEric Cheng #define	FE_FLOW_TAB		0x04	/* Flow is in the flow tab list */
1878275SEric Cheng #define	FE_G_FLOW_HASH		0x08	/* Flow is in the global flow hash */
1888275SEric Cheng #define	FE_INCIPIENT		0x10	/* Being setup */
1898275SEric Cheng #define	FE_CONDEMNED		0x20	/* Being deleted */
1908275SEric Cheng #define	FE_UF_NO_DATAPATH	0x40	/* No datapath setup for User flow */
1918275SEric Cheng #define	FE_MC_NO_DATAPATH	0x80	/* No datapath setup for mac client */
1928275SEric Cheng 
1938275SEric Cheng /* fe_type */
1948275SEric Cheng #define	FLOW_PRIMARY_MAC	0x01 	/* NIC primary MAC address */
1958275SEric Cheng #define	FLOW_VNIC_MAC		0x02	/* VNIC flow */
1968275SEric Cheng #define	FLOW_MCAST		0x04	/* Multicast (and broadcast) */
1978275SEric Cheng #define	FLOW_OTHER		0x08	/* Other flows configured */
1988275SEric Cheng #define	FLOW_USER		0x10	/* User defined flow */
1998275SEric Cheng #define	FLOW_VNIC		FLOW_VNIC_MAC
2008275SEric Cheng #define	FLOW_NO_STATS		0x20	/* Don't create stats for the flow */
2018275SEric Cheng 
2028275SEric Cheng /*
2038275SEric Cheng  * Shared Bandwidth control counters between the soft ring set and its
2048275SEric Cheng  * associated soft rings. In case the flow associated with NIC/VNIC
2058275SEric Cheng  * has a group of Rx rings assigned to it, we have the same
2068275SEric Cheng  * number of soft ring sets as we have the Rx ring in the group
2078275SEric Cheng  * and each individual SRS (and its soft rings) decide when to
2088275SEric Cheng  * poll their Rx ring independently. But if there is a B/W limit
2098275SEric Cheng  * associated with the NIC/VNIC, then the B/W control counter is
2108275SEric Cheng  * shared across all the SRS in the group and their associated
2118275SEric Cheng  * soft rings.
2128275SEric Cheng  *
2138275SEric Cheng  * There is a many to 1 mapping between the SRS and
2148275SEric Cheng  * mac_bw_ctl if the flow has a group of Rx rings associated with
2158275SEric Cheng  * it.
2168275SEric Cheng  */
2178275SEric Cheng typedef struct mac_bw_ctl_s {
2188275SEric Cheng 	kmutex_t	mac_bw_lock;
2198275SEric Cheng 	uint32_t	mac_bw_state;
2208275SEric Cheng 	size_t		mac_bw_sz;	/* ?? Is it needed */
2218275SEric Cheng 	size_t		mac_bw_limit;	/* Max bytes to process per tick */
2228275SEric Cheng 	size_t		mac_bw_used;	/* Bytes processed in current tick */
2238275SEric Cheng 	size_t		mac_bw_drop_threshold; /* Max queue length */
2248275SEric Cheng 	size_t		mac_bw_drop_bytes;
2258275SEric Cheng 	size_t		mac_bw_polled;
2268275SEric Cheng 	size_t		mac_bw_intr;
2278275SEric Cheng 	clock_t		mac_bw_curr_time;
2288275SEric Cheng } mac_bw_ctl_t;
2298275SEric Cheng 
2308275SEric Cheng struct flow_entry_s {					/* Protected by */
2318275SEric Cheng 	struct flow_entry_s	*fe_next;		/* ft_lock */
2328275SEric Cheng 
2338275SEric Cheng 	datalink_id_t		fe_link_id;		/* WO */
2348275SEric Cheng 
2358275SEric Cheng 	/* Properties as specified for this flow */
2368275SEric Cheng 	mac_resource_props_t	fe_resource_props;	/* SL */
2378275SEric Cheng 
2388275SEric Cheng 	/* Properties actually effective at run time for this flow */
2398275SEric Cheng 	mac_resource_props_t	fe_effective_props;	/* SL */
2408275SEric Cheng 
2418275SEric Cheng 	kmutex_t		fe_lock;
2428558SGirish.Moodalbail@Sun.COM 	char			fe_flow_name[MAXFLOWNAMELEN];	/* fe_lock */
2438275SEric Cheng 	flow_desc_t		fe_flow_desc;		/* fe_lock */
2448275SEric Cheng 	kcondvar_t		fe_cv;			/* fe_lock */
2458275SEric Cheng 	/*
2468275SEric Cheng 	 * Initial flow ref is 1 on creation. A thread that lookups the
2478275SEric Cheng 	 * flent typically by a mac_flow_lookup() dynamically holds a ref.
2488275SEric Cheng 	 * If the ref is 1, it means there arent' any upcalls from the driver
2498275SEric Cheng 	 * or downcalls from the stack using this flent. Structures pointing
2508275SEric Cheng 	 * to the flent or flent inserted in lists don't count towards this
2518275SEric Cheng 	 * refcnt. Instead they are tracked using fe_flags. Only a control
2528275SEric Cheng 	 * thread doing a teardown operation deletes the flent, after waiting
2538275SEric Cheng 	 * for upcalls to finish synchronously. The fe_refcnt tracks
2548275SEric Cheng 	 * the number of upcall refs
2558275SEric Cheng 	 */
2568275SEric Cheng 	uint32_t		fe_refcnt;		/* fe_lock */
2578275SEric Cheng 
2588275SEric Cheng 	/*
2598275SEric Cheng 	 * This tracks lookups done using the global hash list for user
2608275SEric Cheng 	 * generated flows. This refcnt only protects the flent itself
2618275SEric Cheng 	 * from disappearing and helps walkers to read the flent info such
2628275SEric Cheng 	 * as flow spec. However the flent may be quiesced and the SRS could
2638275SEric Cheng 	 * be deleted. The fe_user_refcnt tracks the number of global flow
2648275SEric Cheng 	 * has refs.
2658275SEric Cheng 	 */
2668275SEric Cheng 	uint32_t		fe_user_refcnt;		/* fe_lock */
2678275SEric Cheng 	uint_t			fe_flags;		/* fe_lock */
2688275SEric Cheng 
2698275SEric Cheng 	/*
2708275SEric Cheng 	 * Function/args to invoke for delivering matching packets
2718275SEric Cheng 	 * Only the function ff_fn may be changed dynamically and atomically.
2728275SEric Cheng 	 * The ff_arg1 and ff_arg2 are set at creation time and may not
2738275SEric Cheng 	 * be changed.
2748275SEric Cheng 	 */
2758275SEric Cheng 	flow_fn_t		fe_cb_fn;		/* fe_lock */
2768275SEric Cheng 	void 			*fe_cb_arg1;		/* fe_lock */
2778275SEric Cheng 	void			*fe_cb_arg2;		/* fe_lock */
2788275SEric Cheng 
2798275SEric Cheng 	void			*fe_client_cookie;	/* WO */
2808275SEric Cheng 	void			*fe_rx_ring_group;	/* SL */
2818275SEric Cheng 	void			*fe_rx_srs[MAX_RINGS_PER_GROUP]; /* fe_lock */
2828275SEric Cheng 	int			fe_rx_srs_cnt;		/* fe_lock */
283*11878SVenu.Iyer@Sun.COM 	void			*fe_tx_ring_group;
2848275SEric Cheng 	void			*fe_tx_srs;		/* WO */
285*11878SVenu.Iyer@Sun.COM 	int			fe_tx_ring_cnt;
2868275SEric Cheng 
2878275SEric Cheng 	/*
2888275SEric Cheng 	 * This is a unicast flow, and is a mac_client_impl_t
2898275SEric Cheng 	 */
2908275SEric Cheng 	void			*fe_mcip; 		/* WO */
2918275SEric Cheng 
2928275SEric Cheng 	/*
2938275SEric Cheng 	 * Used by mci_flent_list of mac_client_impl_t to track flows sharing
2948275SEric Cheng 	 * the same mac_client_impl_t.
2958275SEric Cheng 	 */
2968275SEric Cheng 	struct flow_entry_s	*fe_client_next;
2978275SEric Cheng 
2988275SEric Cheng 	/*
2998275SEric Cheng 	 * This is a broadcast or multicast flow and is a mac_bcast_grp_t
3008275SEric Cheng 	 */
3018275SEric Cheng 	void			*fe_mbg;		/* WO */
3028275SEric Cheng 	uint_t			fe_type;		/* WO */
3038275SEric Cheng 
3048275SEric Cheng 	/*
3058275SEric Cheng 	 * BW control info.
3068275SEric Cheng 	 */
3078275SEric Cheng 	mac_bw_ctl_t		fe_tx_bw;
3088275SEric Cheng 	mac_bw_ctl_t		fe_rx_bw;
3098275SEric Cheng 
3108275SEric Cheng 	/*
3118275SEric Cheng 	 * Used by flow table lookup code
3128275SEric Cheng 	 */
3138275SEric Cheng 	flow_match_fn_t		fe_match;
3148275SEric Cheng 
3158275SEric Cheng 	/*
3168275SEric Cheng 	 * Used by mac_flow_remove().
3178275SEric Cheng 	 */
3188275SEric Cheng 	int			fe_index;
3198275SEric Cheng 	flow_tab_t		*fe_flow_tab;
3208275SEric Cheng 
3218275SEric Cheng 	kstat_t			*fe_ksp;
322*11878SVenu.Iyer@Sun.COM 	kstat_t			*fe_misc_stat_ksp;
323*11878SVenu.Iyer@Sun.COM 
3248275SEric Cheng 	boolean_t		fe_desc_logged;
3258275SEric Cheng 	uint64_t		fe_nic_speed;
3268275SEric Cheng };
3278275SEric Cheng 
3288275SEric Cheng /*
3298275SEric Cheng  * Various structures used by the flows framework for keeping track
3308275SEric Cheng  * of packet state information.
3318275SEric Cheng  */
3328275SEric Cheng 
3338275SEric Cheng /* Layer 2 */
3348275SEric Cheng typedef struct flow_l2info_s {
3358275SEric Cheng 	uchar_t		*l2_start;
3368275SEric Cheng 	uint8_t		*l2_daddr;
3378275SEric Cheng 	uint16_t	l2_vid;
3388275SEric Cheng 	uint32_t	l2_sap;
3398275SEric Cheng 	uint_t		l2_hdrsize;
3408275SEric Cheng } flow_l2info_t;
3418275SEric Cheng 
3428275SEric Cheng /* Layer 3 */
3438275SEric Cheng typedef struct flow_l3info_s {
3448275SEric Cheng 	uchar_t		*l3_start;
3458275SEric Cheng 	uint8_t		l3_protocol;
3468275SEric Cheng 	uint8_t		l3_version;
3478275SEric Cheng 	boolean_t	l3_dst_or_src;
3488275SEric Cheng 	uint_t		l3_hdrsize;
3498275SEric Cheng 	boolean_t	l3_fragmented;
3508275SEric Cheng } flow_l3info_t;
3518275SEric Cheng 
3528275SEric Cheng /* Layer 4 */
3538275SEric Cheng typedef struct flow_l4info_s {
3548275SEric Cheng 	uchar_t		*l4_start;
3558275SEric Cheng 	uint16_t	l4_src_port;
3568275SEric Cheng 	uint16_t	l4_dst_port;
3578275SEric Cheng 	uint16_t	l4_hash_port;
3588275SEric Cheng } flow_l4info_t;
3598275SEric Cheng 
3608275SEric Cheng /*
3618275SEric Cheng  * Combined state structure.
3628275SEric Cheng  * Holds flow direction and an mblk_t pointer.
3638275SEric Cheng  */
3648275SEric Cheng struct flow_state_s {
3658275SEric Cheng 	uint_t		fs_flags;
3668275SEric Cheng 	mblk_t		*fs_mp;
3678275SEric Cheng 	flow_l2info_t	fs_l2info;
3688275SEric Cheng 	flow_l3info_t	fs_l3info;
3698275SEric Cheng 	flow_l4info_t	fs_l4info;
3708275SEric Cheng };
3718275SEric Cheng 
3728275SEric Cheng /*
3738275SEric Cheng  * Flow ops vector.
3748275SEric Cheng  * There are two groups of functions. The ones ending with _fe are
3758275SEric Cheng  * called when a flow is being added. The others (hash, accept) are
3768275SEric Cheng  * called at flow lookup time.
3778275SEric Cheng  */
3788275SEric Cheng #define	FLOW_MAX_ACCEPT	16
3798275SEric Cheng typedef struct flow_ops_s {
3808275SEric Cheng 	/*
3818275SEric Cheng 	 * fo_accept_fe():
3828275SEric Cheng 	 * Validates the contents of the flow and checks whether
3838275SEric Cheng 	 * it's compatible with the flow table. sets the fe_match
3848275SEric Cheng 	 * function of the flow.
3858275SEric Cheng 	 */
3868275SEric Cheng 	int		(*fo_accept_fe)(flow_tab_t *, flow_entry_t *);
3878275SEric Cheng 	/*
3888275SEric Cheng 	 * fo_hash_fe():
3898275SEric Cheng 	 * Generates a hash index to the flow table. This function
3908275SEric Cheng 	 * must use the same algorithm as fo_hash(), which is used
3918275SEric Cheng 	 * by the flow lookup code path.
3928275SEric Cheng 	 */
3938275SEric Cheng 	uint32_t	(*fo_hash_fe)(flow_tab_t *, flow_entry_t *);
3948275SEric Cheng 	/*
3958275SEric Cheng 	 * fo_match_fe():
3968275SEric Cheng 	 * This is used for finding identical flows.
3978275SEric Cheng 	 */
3988275SEric Cheng 	boolean_t	(*fo_match_fe)(flow_tab_t *, flow_entry_t *,
3998275SEric Cheng 			    flow_entry_t *);
4008275SEric Cheng 	/*
4018275SEric Cheng 	 * fo_insert_fe():
4028275SEric Cheng 	 * Used for inserting a flow to a flow chain.
4038275SEric Cheng 	 * Protocols that have special ordering requirements would
4048275SEric Cheng 	 * need to implement this. For those that don't,
4058275SEric Cheng 	 * flow_generic_insert_fe() may be used.
4068275SEric Cheng 	 */
4078275SEric Cheng 	int		(*fo_insert_fe)(flow_tab_t *, flow_entry_t **,
4088275SEric Cheng 			    flow_entry_t *);
4098275SEric Cheng 
4108275SEric Cheng 	/*
4118275SEric Cheng 	 * Calculates the flow hash index based on the accumulated
4128275SEric Cheng 	 * state in flow_state_t. Must use the same algorithm as
4138275SEric Cheng 	 * fo_hash_fe().
4148275SEric Cheng 	 */
4158275SEric Cheng 	uint32_t	(*fo_hash)(flow_tab_t *, flow_state_t *);
4168275SEric Cheng 
4178275SEric Cheng 	/*
4188275SEric Cheng 	 * Array of accept fuctions.
4198275SEric Cheng 	 * Each function in the array will accumulate enough state
4208275SEric Cheng 	 * (header length, protocol) to allow the next function to
4218275SEric Cheng 	 * proceed. We support up to FLOW_MAX_ACCEPT functions which
4228275SEric Cheng 	 * should be sufficient for all practical purposes.
4238275SEric Cheng 	 */
4248275SEric Cheng 	int		(*fo_accept[FLOW_MAX_ACCEPT])(flow_tab_t *,
4258275SEric Cheng 			    flow_state_t *);
4268275SEric Cheng } flow_ops_t;
4278275SEric Cheng 
4288275SEric Cheng /*
4298275SEric Cheng  * Generic flow table.
4308275SEric Cheng  */
4318275SEric Cheng struct flow_tab_s {
4328275SEric Cheng 	krwlock_t		ft_lock;
4338275SEric Cheng 	/*
4348275SEric Cheng 	 * Contains a list of functions (described above)
4358275SEric Cheng 	 * specific to this table type.
4368275SEric Cheng 	 */
4378275SEric Cheng 	flow_ops_t		ft_ops;
4388275SEric Cheng 
4398275SEric Cheng 	/*
4408275SEric Cheng 	 * Indicates what types of flows are supported.
4418275SEric Cheng 	 */
4428275SEric Cheng 	flow_mask_t		ft_mask;
4438275SEric Cheng 
4448275SEric Cheng 	/*
4458275SEric Cheng 	 * An array of flow_entry_t * of size ft_size.
4468275SEric Cheng 	 * Each element is the beginning of a hash chain.
4478275SEric Cheng 	 */
4488275SEric Cheng 	flow_entry_t		**ft_table;
4498275SEric Cheng 	uint_t			ft_size;
4508275SEric Cheng 
4518275SEric Cheng 	/*
4528275SEric Cheng 	 * The number of flows inserted into ft_table.
4538275SEric Cheng 	 */
4548275SEric Cheng 	uint_t			ft_flow_count;
4558275SEric Cheng 	struct mac_impl_s	*ft_mip;
4568275SEric Cheng 	struct mac_client_impl_s	*ft_mcip;
4578275SEric Cheng };
4588275SEric Cheng 
4598275SEric Cheng /*
4608275SEric Cheng  * This is used for describing what type of flow table can be created.
4618275SEric Cheng  * mac_flow.c contains a list of these structures.
4628275SEric Cheng  */
4638275SEric Cheng typedef struct flow_tab_info_s {
4648275SEric Cheng 	flow_ops_t		*fti_ops;
4658275SEric Cheng 	flow_mask_t		fti_mask;
4668275SEric Cheng 	uint_t			fti_size;
4678275SEric Cheng } flow_tab_info_t;
4688275SEric Cheng 
4698275SEric Cheng #define	FLOW_TAB_EMPTY(ft)	((ft) == NULL || (ft)->ft_flow_count == 0)
4708275SEric Cheng 
4718275SEric Cheng 
472*11878SVenu.Iyer@Sun.COM #define	MCIP_STAT_UPDATE(m, s, c) {					\
473*11878SVenu.Iyer@Sun.COM 	((mac_client_impl_t *)(m))->mci_misc_stat.mms_##s		\
474*11878SVenu.Iyer@Sun.COM 	+= ((uint64_t)(c));						\
475*11878SVenu.Iyer@Sun.COM }
476*11878SVenu.Iyer@Sun.COM 
477*11878SVenu.Iyer@Sun.COM #define	SRS_RX_STAT_UPDATE(m, s, c)  {					\
478*11878SVenu.Iyer@Sun.COM 	((mac_soft_ring_set_t *)(m))->srs_rx.sr_stat.mrs_##s		\
479*11878SVenu.Iyer@Sun.COM 	+= ((uint64_t)(c));						\
4808275SEric Cheng }
4818275SEric Cheng 
482*11878SVenu.Iyer@Sun.COM #define	SRS_TX_STAT_UPDATE(m, s, c)  {					\
483*11878SVenu.Iyer@Sun.COM 	((mac_soft_ring_set_t *)(m))->srs_tx.st_stat.mts_##s		\
484*11878SVenu.Iyer@Sun.COM 	+= ((uint64_t)(c));						\
485*11878SVenu.Iyer@Sun.COM }
486*11878SVenu.Iyer@Sun.COM 
487*11878SVenu.Iyer@Sun.COM #define	SRS_TX_STATS_UPDATE(m, s) {					\
488*11878SVenu.Iyer@Sun.COM 	SRS_TX_STAT_UPDATE((m), opackets, (s)->mts_opackets);		\
489*11878SVenu.Iyer@Sun.COM 	SRS_TX_STAT_UPDATE((m), obytes, (s)->mts_obytes);		\
490*11878SVenu.Iyer@Sun.COM 	SRS_TX_STAT_UPDATE((m), oerrors, (s)->mts_oerrors);		\
491*11878SVenu.Iyer@Sun.COM }
492*11878SVenu.Iyer@Sun.COM 
493*11878SVenu.Iyer@Sun.COM #define	SOFTRING_TX_STAT_UPDATE(m, s, c)  {				\
494*11878SVenu.Iyer@Sun.COM 	((mac_soft_ring_t *)(m))->s_st_stat.mts_##s += ((uint64_t)(c));	\
495*11878SVenu.Iyer@Sun.COM }
496*11878SVenu.Iyer@Sun.COM 
497*11878SVenu.Iyer@Sun.COM #define	SOFTRING_TX_STATS_UPDATE(m, s) {				\
498*11878SVenu.Iyer@Sun.COM 	SOFTRING_TX_STAT_UPDATE((m), opackets, (s)->mts_opackets);	\
499*11878SVenu.Iyer@Sun.COM 	SOFTRING_TX_STAT_UPDATE((m), obytes, (s)->mts_obytes);		\
500*11878SVenu.Iyer@Sun.COM 	SOFTRING_TX_STAT_UPDATE((m), oerrors, (s)->mts_oerrors);	\
5018275SEric Cheng }
5028275SEric Cheng 
5038275SEric Cheng extern void	mac_flow_init();
5048275SEric Cheng extern void	mac_flow_fini();
5058275SEric Cheng extern int	mac_flow_create(flow_desc_t *, mac_resource_props_t *,
5068275SEric Cheng 		    char *, void *, uint_t, flow_entry_t **);
5078275SEric Cheng 
5088275SEric Cheng extern int	mac_flow_add(flow_tab_t *, flow_entry_t *);
5098275SEric Cheng extern int	mac_flow_add_subflow(mac_client_handle_t, flow_entry_t *,
5108275SEric Cheng 		    boolean_t);
5118275SEric Cheng extern int	mac_flow_hash_add(flow_entry_t *);
5128275SEric Cheng extern int	mac_flow_lookup_byname(char *, flow_entry_t **);
5138275SEric Cheng extern int	mac_flow_lookup(flow_tab_t *, mblk_t *, uint_t,
5148275SEric Cheng 		    flow_entry_t **);
5158275SEric Cheng 
5168275SEric Cheng extern int	mac_flow_walk(flow_tab_t *, int (*)(flow_entry_t *, void *),
5178275SEric Cheng 		    void *);
5188275SEric Cheng 
5198275SEric Cheng extern int	mac_flow_walk_nolock(flow_tab_t *,
5208275SEric Cheng 		    int (*)(flow_entry_t *, void *), void *);
5218275SEric Cheng 
5228275SEric Cheng extern void	mac_flow_modify(flow_tab_t *, flow_entry_t *,
5238275SEric Cheng 		    mac_resource_props_t *);
5248275SEric Cheng 
5258275SEric Cheng extern void	*mac_flow_get_client_cookie(flow_entry_t *);
5268275SEric Cheng 
5278275SEric Cheng extern uint32_t	mac_flow_modify_props(flow_entry_t *, mac_resource_props_t *);
5288275SEric Cheng 
5298275SEric Cheng extern int	mac_flow_update(flow_tab_t *, flow_entry_t *, flow_desc_t *);
5308275SEric Cheng extern void	mac_flow_get_desc(flow_entry_t *, flow_desc_t *);
5318275SEric Cheng extern void	mac_flow_set_desc(flow_entry_t *, flow_desc_t *);
5328275SEric Cheng 
5338275SEric Cheng extern void	mac_flow_remove(flow_tab_t *, flow_entry_t *, boolean_t);
5348275SEric Cheng extern void	mac_flow_hash_remove(flow_entry_t *);
5358275SEric Cheng extern void	mac_flow_wait(flow_entry_t *, mac_flow_state_t);
5368275SEric Cheng extern void	mac_flow_quiesce(flow_entry_t *);
5378275SEric Cheng extern void	mac_flow_restart(flow_entry_t *);
5388275SEric Cheng extern void	mac_flow_cleanup(flow_entry_t *);
5398275SEric Cheng extern void	mac_flow_destroy(flow_entry_t *);
5408275SEric Cheng 
5418275SEric Cheng extern void	mac_flow_tab_create(flow_ops_t *, flow_mask_t, uint_t,
5428275SEric Cheng 		    struct mac_impl_s *, flow_tab_t **);
5438275SEric Cheng extern void	mac_flow_l2tab_create(struct mac_impl_s *, flow_tab_t **);
5448275SEric Cheng extern void	mac_flow_tab_destroy(flow_tab_t *);
5458275SEric Cheng extern void	mac_flow_drop(void *, void *, mblk_t *);
5468275SEric Cheng extern void	flow_stat_destroy(flow_entry_t *);
5478275SEric Cheng 
5488275SEric Cheng #ifdef	__cplusplus
5498275SEric Cheng }
5508275SEric Cheng #endif
5518275SEric Cheng 
5528275SEric Cheng #endif	/* _MAC_FLOW_IMPL_H */
553