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