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 /* 22*11878SVenu.Iyer@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 238275SEric Cheng * Use is subject to license terms. 248275SEric Cheng */ 258275SEric Cheng 268275SEric Cheng #ifndef _SYS_MAC_CLIENT_IMPL_H 278275SEric Cheng #define _SYS_MAC_CLIENT_IMPL_H 288275SEric Cheng 298275SEric Cheng #include <sys/modhash.h> 308275SEric Cheng #include <sys/mac_client.h> 318275SEric Cheng #include <sys/mac_provider.h> 328275SEric Cheng #include <sys/mac.h> 338275SEric Cheng #include <sys/mac_impl.h> 34*11878SVenu.Iyer@Sun.COM #include <sys/mac_stat.h> 358275SEric Cheng #include <net/if.h> 368275SEric Cheng #include <sys/mac_flow_impl.h> 378275SEric Cheng 388275SEric Cheng #ifdef __cplusplus 398275SEric Cheng extern "C" { 408275SEric Cheng #endif 418275SEric Cheng 428275SEric Cheng extern kmem_cache_t *mac_client_impl_cache; 438275SEric Cheng extern kmem_cache_t *mac_unicast_impl_cache; 448275SEric Cheng extern kmem_cache_t *mac_promisc_impl_cache; 458275SEric Cheng 468275SEric Cheng /* 478275SEric Cheng * Need a list to chain all VIDs assigned to a client. Normally, one 488275SEric Cheng * MAC client only has one VID. But vsw might need multiple VIDs. 498275SEric Cheng */ 508275SEric Cheng typedef struct mac_unicast_impl_s { /* Protected by */ 518275SEric Cheng struct mac_unicast_impl_s *mui_next; /* SL */ 528275SEric Cheng mac_address_t *mui_map; /* SL */ 538275SEric Cheng uint16_t mui_vid; /* SL */ 548275SEric Cheng } mac_unicast_impl_t; 558275SEric Cheng 569473SVenu.Iyer@Sun.COM #define MAC_CLIENT_FLAGS_PRIMARY 0X0001 579473SVenu.Iyer@Sun.COM #define MAC_CLIENT_FLAGS_VNIC_PRIMARY 0x0002 589473SVenu.Iyer@Sun.COM #define MAC_CLIENT_FLAGS_MULTI_PRIMARY 0x0004 599473SVenu.Iyer@Sun.COM #define MAC_CLIENT_FLAGS_PASSIVE_PRIMARY 0x0008 608275SEric Cheng 618275SEric Cheng /* 628275SEric Cheng * One of these is instantiated per MAC client promiscuous callback. 638275SEric Cheng * 648275SEric Cheng * Each element of this structure belongs to two linked list. One 658275SEric Cheng * for the mac_client_impl_t (mci_promisc_list) which created allocated 668275SEric Cheng * the callback, the other for the mac_impl_t (mi_promisc_list) corresponding 678275SEric Cheng * to the MAC client. 688275SEric Cheng * The former allows us to do bookkeeping, the latter allows us 698275SEric Cheng * to more efficiently dispatch packets to the promiscuous callbacks. 708275SEric Cheng */ 718275SEric Cheng typedef struct mac_promisc_impl_s { /* Protected by */ 728275SEric Cheng mac_cb_t mpi_mci_link; /* mi_promisc_lock */ 738275SEric Cheng mac_cb_t mpi_mi_link; /* mi_promisc_lock */ 748275SEric Cheng mac_client_promisc_type_t mpi_type; /* WO */ 758275SEric Cheng mac_rx_t mpi_fn; /* WO */ 768275SEric Cheng void *mpi_arg; /* WO */ 778275SEric Cheng struct mac_client_impl_s *mpi_mcip; /* WO */ 788275SEric Cheng boolean_t mpi_no_tx_loop; /* WO */ 798275SEric Cheng boolean_t mpi_no_phys; /* WO */ 808833SVenu.Iyer@Sun.COM boolean_t mpi_strip_vlan_tag; /* WO */ 8110639SDarren.Reed@Sun.COM boolean_t mpi_no_copy; /* WO */ 828275SEric Cheng } mac_promisc_impl_t; 838275SEric Cheng 848275SEric Cheng typedef union mac_tx_percpu_s { 858275SEric Cheng struct { 868275SEric Cheng kmutex_t _pcpu_tx_lock; 878275SEric Cheng uint_t _pcpu_tx_refcnt; 888275SEric Cheng } pcpu_lr; 898275SEric Cheng uchar_t pcpu_pad[64]; 908275SEric Cheng } mac_tx_percpu_t; 918275SEric Cheng 928275SEric Cheng #define pcpu_tx_lock pcpu_lr._pcpu_tx_lock 938275SEric Cheng #define pcpu_tx_refcnt pcpu_lr._pcpu_tx_refcnt 948275SEric Cheng 958275SEric Cheng /* 968275SEric Cheng * One of these is instanciated for each MAC client. 978275SEric Cheng */ 988275SEric Cheng struct mac_client_impl_s { /* Protected by */ 998275SEric Cheng struct mac_client_impl_s *mci_client_next; /* mi_rw_lock */ 1008275SEric Cheng char mci_name[MAXNAMELEN]; /* mi_rw_lock */ 1018275SEric Cheng /* 1028275SEric Cheng * This flow entry will contain all the internal constructs 1038275SEric Cheng * such as SRS etc. for this MAC client. The MAC client may 1048275SEric Cheng * have more than one flow corresponding to each upper client 1058275SEric Cheng * sharing this mac_client_impl_t. 1068275SEric Cheng */ 1078275SEric Cheng flow_entry_t *mci_flent; /* mi_rw_lock */ 1088275SEric Cheng struct mac_impl_s *mci_mip; /* WO */ 1098275SEric Cheng /* 1108275SEric Cheng * If this is a client that has a pass thru MAC (e.g. a VNIC), 1118275SEric Cheng * then we also keep the handle for the client's upper MAC. 1128275SEric Cheng */ 1138275SEric Cheng struct mac_impl_s *mci_upper_mip; /* WO */ 1148275SEric Cheng 1158275SEric Cheng uint32_t mci_state_flags; /* WO */ 1168275SEric Cheng mac_rx_t mci_rx_fn; /* Rx Quiescence */ 1178275SEric Cheng void *mci_rx_arg; /* Rx Quiescence */ 1188275SEric Cheng mac_direct_rx_t mci_direct_rx_fn; /* SL */ 1198275SEric Cheng void *mci_direct_rx_arg; /* SL */ 1209473SVenu.Iyer@Sun.COM mac_rx_t mci_rx_p_fn; /* Rx Quiescence */ 1219473SVenu.Iyer@Sun.COM void *mci_rx_p_arg; /* Rx Quiescence */ 1229473SVenu.Iyer@Sun.COM void *mci_p_unicast_list; 1238275SEric Cheng 1248275SEric Cheng mac_cb_t *mci_promisc_list; /* mi_promisc_lock */ 1258275SEric Cheng 1268275SEric Cheng mac_address_t *mci_unicast; 1278275SEric Cheng uint32_t mci_flags; /* SL */ 1288275SEric Cheng krwlock_t mci_rw_lock; 1298275SEric Cheng mac_unicast_impl_t *mci_unicast_list; /* mci_rw_lock */ 1308275SEric Cheng /* 1318275SEric Cheng * The mac_client_impl_t may be shared by multiple clients, i.e 1328275SEric Cheng * multiple VLANs sharing the same MAC client. In this case the 1338275SEric Cheng * address/vid tubles differ and are each associated with their 1348275SEric Cheng * own flow entry, but the rest underlying components SRS, etc, 1358275SEric Cheng * are common. 1368275SEric Cheng */ 1378275SEric Cheng flow_entry_t *mci_flent_list; /* mci_rw_lock */ 1388275SEric Cheng uint_t mci_nflents; /* mci_rw_lock */ 1398275SEric Cheng uint_t mci_nvids; /* mci_rw_lock */ 1408275SEric Cheng 1418275SEric Cheng /* Resource Management Functions */ 1428275SEric Cheng mac_resource_add_t mci_resource_add; /* SL */ 1438275SEric Cheng mac_resource_remove_t mci_resource_remove; /* SL */ 1448275SEric Cheng mac_resource_quiesce_t mci_resource_quiesce; /* SL */ 1458275SEric Cheng mac_resource_restart_t mci_resource_restart; /* SL */ 1468275SEric Cheng mac_resource_bind_t mci_resource_bind; /* SL */ 1478275SEric Cheng void *mci_resource_arg; /* SL */ 1488275SEric Cheng 1498275SEric Cheng 1508275SEric Cheng /* Tx notify callback */ 1518275SEric Cheng kmutex_t mci_tx_cb_lock; 1528275SEric Cheng mac_cb_info_t mci_tx_notify_cb_info; /* cb list info */ 1538275SEric Cheng mac_cb_t *mci_tx_notify_cb_list; /* The cb list */ 1548275SEric Cheng uintptr_t mci_tx_notify_id; 1558275SEric Cheng 1568275SEric Cheng /* per MAC client stats */ /* None */ 157*11878SVenu.Iyer@Sun.COM mac_misc_stats_t mci_misc_stat; 1588275SEric Cheng 1598275SEric Cheng flow_tab_t *mci_subflow_tab; /* Rx quiescence */ 1608275SEric Cheng 1618275SEric Cheng /* 1628275SEric Cheng * Priority range for this MAC client. This the range 1638275SEric Cheng * corresponding to the priority configured (nr_flow_priority). 1648275SEric Cheng */ 1658275SEric Cheng pri_t mci_min_pri; 1668275SEric Cheng pri_t mci_max_pri; 1678275SEric Cheng 1688275SEric Cheng /* 1698275SEric Cheng * Hybrid I/O related definitions. 1708275SEric Cheng */ 1718275SEric Cheng mac_share_handle_t mci_share; 1728275SEric Cheng 1738275SEric Cheng /* for multicast support */ 1748275SEric Cheng struct mac_mcast_addrs_s *mci_mcast_addrs; /* mi_rw_lock */ 1758275SEric Cheng 1768275SEric Cheng /* 177*11878SVenu.Iyer@Sun.COM * Mac protection related fields 178*11878SVenu.Iyer@Sun.COM */ 179*11878SVenu.Iyer@Sun.COM kmutex_t mci_protect_lock; 180*11878SVenu.Iyer@Sun.COM uint32_t mci_protect_flags; /* SL */ 181*11878SVenu.Iyer@Sun.COM in6_addr_t mci_v6_local_addr; /* SL */ 182*11878SVenu.Iyer@Sun.COM avl_tree_t mci_v4_pending_txn; /* mci_protect_lock */ 183*11878SVenu.Iyer@Sun.COM avl_tree_t mci_v4_completed_txn; /* mci_protect_lock */ 184*11878SVenu.Iyer@Sun.COM avl_tree_t mci_v4_dyn_ip; /* mci_protect_lock */ 185*11878SVenu.Iyer@Sun.COM avl_tree_t mci_v6_pending_txn; /* mci_protect_lock */ 186*11878SVenu.Iyer@Sun.COM avl_tree_t mci_v6_cid; /* mci_protect_lock */ 187*11878SVenu.Iyer@Sun.COM avl_tree_t mci_v6_dyn_ip; /* mci_protect_lock */ 188*11878SVenu.Iyer@Sun.COM timeout_id_t mci_txn_cleanup_tid; /* mci_protect_lock */ 189*11878SVenu.Iyer@Sun.COM 190*11878SVenu.Iyer@Sun.COM /* 1918275SEric Cheng * Protected by mci_tx_pcpu[0].pcpu_tx_lock 1928275SEric Cheng */ 1938275SEric Cheng uint_t mci_tx_flag; 1948275SEric Cheng kcondvar_t mci_tx_cv; 1958275SEric Cheng 1968275SEric Cheng /* Must be last in the structure for dynamic sizing */ 1978275SEric Cheng mac_tx_percpu_t mci_tx_pcpu[1]; /* SL */ 1988275SEric Cheng }; 1998275SEric Cheng 2008275SEric Cheng #define MAC_CLIENT_IMPL_SIZE \ 2018275SEric Cheng (sizeof (mac_client_impl_t) + \ 2028275SEric Cheng (mac_tx_percpu_cnt * sizeof (mac_tx_percpu_t))) 2038275SEric Cheng 2048275SEric Cheng extern int mac_tx_percpu_cnt; 2058275SEric Cheng 2068275SEric Cheng #define MCIP_TX_SRS(mcip) \ 2078275SEric Cheng ((mcip)->mci_flent == NULL ? NULL : (mcip)->mci_flent->fe_tx_srs) 2088275SEric Cheng 2098275SEric Cheng /* Defensive coding, non-null mcip_flent could be an assert */ 2108275SEric Cheng 2118275SEric Cheng #define MCIP_DATAPATH_SETUP(mcip) \ 2128275SEric Cheng ((mcip)->mci_flent == NULL ? B_FALSE : \ 2138275SEric Cheng !((mcip)->mci_flent->fe_flags & FE_MC_NO_DATAPATH)) 2148275SEric Cheng 2158275SEric Cheng #define MCIP_RESOURCE_PROPS(mcip) \ 2168275SEric Cheng ((mcip)->mci_flent == NULL ? NULL : \ 2178275SEric Cheng &(mcip)->mci_flent->fe_resource_props) 2188275SEric Cheng 2198275SEric Cheng #define MCIP_EFFECTIVE_PROPS(mcip) \ 2208275SEric Cheng (mcip->mci_flent == NULL ? NULL : \ 2218275SEric Cheng &(mcip)->mci_flent->fe_effective_props) 2228275SEric Cheng 2238275SEric Cheng #define MCIP_RESOURCE_PROPS_MASK(mcip) \ 2248275SEric Cheng ((mcip)->mci_flent == NULL ? 0 : \ 2258275SEric Cheng (mcip)->mci_flent->fe_resource_props.mrp_mask) 2268275SEric Cheng 2278275SEric Cheng #define MCIP_RESOURCE_PROPS_MAXBW(mcip) \ 2288275SEric Cheng ((mcip)->mci_flent == NULL ? 0 : \ 2298275SEric Cheng (mcip)->mci_flent->fe_resource_props.mrp_maxbw) 2308275SEric Cheng 2318275SEric Cheng #define MCIP_RESOURCE_PROPS_PRIORITY(mcip) \ 2328275SEric Cheng ((mcip)->mci_flent == NULL ? 0 : \ 2338275SEric Cheng (mcip)->mci_flent->fe_resource_props.mrp_priority) 2348275SEric Cheng 2358275SEric Cheng #define MCIP_RESOURCE_PROPS_CPUS(mcip) \ 2368275SEric Cheng ((mcip)->mci_flent == NULL ? 0 : \ 2378275SEric Cheng &(mcip)->mci_flent->fe_resource_props.mrp_cpus) 2388275SEric Cheng 2398275SEric Cheng #define MCIP_RESOURCE_PROPS_NCPUS(mcip) \ 2408275SEric Cheng ((mcip)->mci_flent == NULL ? 0 : \ 2418275SEric Cheng (mcip)->mci_flent->fe_resource_props.mrp_ncpus) 2428275SEric Cheng 2438275SEric Cheng #define MCIP_RESOURCE_PROPS_CPU(mcip) \ 2448275SEric Cheng ((mcip)->mci_flent == NULL ? 0 : \ 2458275SEric Cheng (mcip)->mci_flent->fe_resource_props.mrp_ncpu) 2468275SEric Cheng 2478275SEric Cheng /* 2488275SEric Cheng * We validate the VLAN id of the packet w.r.t the client's vid, 2498275SEric Cheng * if required (i.e. !MCIS_DISABLE_TX_VID_CHECK). DLS clients 2508275SEric Cheng * will have MCIS_DISABLE_TX_VID_CHECK set. 2518275SEric Cheng * (In the case of aggr when we get back packets, due to 2528275SEric Cheng * the underlying driver being flow controlled, we won't 2538275SEric Cheng * drop the packet even if it is VLAN tagged as we 2548275SEric Cheng * don't set MCIS_DISABLE_TX_VID_CHECK for an aggr.) 2558275SEric Cheng */ 2568275SEric Cheng #define MAC_VID_CHECK_NEEDED(mcip) \ 2578275SEric Cheng (((mcip)->mci_state_flags & MCIS_DISABLE_TX_VID_CHECK) == 0 && \ 2588275SEric Cheng (mcip)->mci_mip->mi_info.mi_nativemedia == DL_ETHER) 2598275SEric Cheng 2608275SEric Cheng #define MAC_VID_CHECK(mcip, mp, err) { \ 2618275SEric Cheng if (ntohs(((struct ether_header *)(mp)->b_rptr)->ether_type) == \ 2628275SEric Cheng ETHERTYPE_VLAN) { \ 2638275SEric Cheng /* \ 2648275SEric Cheng * err is set to EINVAL (so the caller can take the \ 2658275SEric Cheng * appropriate action. e.g. freemsg()) for two cases: \ 2668275SEric Cheng * -client is not responsible for filling in the vid. \ 2678275SEric Cheng * -client is responsible for filling in the vid, but \ 2688275SEric Cheng * the vid doesn't match the vid of the MAC client. \ 2698275SEric Cheng */ \ 2708275SEric Cheng (err) = EINVAL; \ 2718275SEric Cheng if (((mcip)->mci_state_flags & MCIS_TAG_DISABLE) != 0) {\ 2728275SEric Cheng struct ether_vlan_header *evhp; \ 2738275SEric Cheng uint16_t vlanid; \ 2748275SEric Cheng \ 2758275SEric Cheng evhp = (struct ether_vlan_header *)(mp)->b_rptr;\ 2768275SEric Cheng vlanid = VLAN_ID(ntohs(evhp->ether_tci)); \ 2778275SEric Cheng if (mac_client_check_flow_vid((mcip), vlanid)) \ 2788275SEric Cheng (err) = 0; \ 2798275SEric Cheng } \ 2808275SEric Cheng } \ 2818275SEric Cheng } 2828275SEric Cheng 2838275SEric Cheng #define MAC_TAG_NEEDED(mcip) \ 2848275SEric Cheng (((mcip)->mci_state_flags & MCIS_TAG_DISABLE) == 0 && \ 2858275SEric Cheng (mcip)->mci_nvids == 1) \ 2868275SEric Cheng 2878275SEric Cheng /* MCI state flags */ 2888275SEric Cheng #define MCIS_IS_VNIC 0x0001 2898275SEric Cheng #define MCIS_EXCLUSIVE 0x0002 2908275SEric Cheng #define MCIS_TAG_DISABLE 0x0004 2918275SEric Cheng #define MCIS_STRIP_DISABLE 0x0008 2928275SEric Cheng #define MCIS_IS_AGGR_PORT 0x0010 2938275SEric Cheng #define MCIS_CLIENT_POLL_CAPABLE 0x0020 2948275SEric Cheng #define MCIS_DESC_LOGGED 0x0040 2958275SEric Cheng #define MCIS_SHARE_BOUND 0x0080 296*11878SVenu.Iyer@Sun.COM #define MCIS_DISABLE_TX_VID_CHECK 0x0100 297*11878SVenu.Iyer@Sun.COM #define MCIS_USE_DATALINK_NAME 0x0200 298*11878SVenu.Iyer@Sun.COM #define MCIS_UNICAST_HW 0x0400 299*11878SVenu.Iyer@Sun.COM #define MCIS_IS_AGGR 0x0800 300*11878SVenu.Iyer@Sun.COM #define MCIS_RX_BYPASS_DISABLE 0x1000 301*11878SVenu.Iyer@Sun.COM #define MCIS_NO_UNICAST_ADDR 0x2000 302*11878SVenu.Iyer@Sun.COM 303*11878SVenu.Iyer@Sun.COM /* Mac protection flags */ 304*11878SVenu.Iyer@Sun.COM #define MPT_FLAG_V6_LOCAL_ADDR_SET 0x0001 3058275SEric Cheng 3068275SEric Cheng /* in mac_client.c */ 3078275SEric Cheng extern void mac_promisc_client_dispatch(mac_client_impl_t *, mblk_t *); 3088275SEric Cheng extern void mac_client_init(void); 3098275SEric Cheng extern void mac_client_fini(void); 3108275SEric Cheng extern void mac_promisc_dispatch(mac_impl_t *, mblk_t *, 3118275SEric Cheng mac_client_impl_t *); 3128275SEric Cheng 313*11878SVenu.Iyer@Sun.COM extern int mac_validate_props(mac_impl_t *, mac_resource_props_t *); 3148275SEric Cheng 3158275SEric Cheng extern mac_client_impl_t *mac_vnic_lower(mac_impl_t *); 3168275SEric Cheng extern mac_client_impl_t *mac_primary_client_handle(mac_impl_t *); 3178275SEric Cheng extern uint16_t i_mac_flow_vid(flow_entry_t *); 3188275SEric Cheng extern boolean_t i_mac_capab_get(mac_handle_t, mac_capab_t, void *); 3198275SEric Cheng 3208275SEric Cheng extern void mac_unicast_update_clients(mac_impl_t *, mac_address_t *); 3218275SEric Cheng extern void mac_update_resources(mac_resource_props_t *, 3228275SEric Cheng mac_resource_props_t *, boolean_t); 3238275SEric Cheng 3248275SEric Cheng boolean_t mac_client_check_flow_vid(mac_client_impl_t *, uint16_t); 3258275SEric Cheng 3268275SEric Cheng extern boolean_t mac_is_primary_client(mac_client_impl_t *); 3278275SEric Cheng 328*11878SVenu.Iyer@Sun.COM extern int mac_client_set_rings_prop(mac_client_impl_t *, 329*11878SVenu.Iyer@Sun.COM mac_resource_props_t *, mac_resource_props_t *); 330*11878SVenu.Iyer@Sun.COM extern void mac_set_prim_vlan_rings(mac_impl_t *, mac_resource_props_t *); 331*11878SVenu.Iyer@Sun.COM 3328275SEric Cheng #ifdef __cplusplus 3338275SEric Cheng } 3348275SEric Cheng #endif 3358275SEric Cheng 3368275SEric Cheng #endif /* _SYS_MAC_CLIENT_IMPL_H */ 337