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