1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #ifndef _SYS_AGGR_IMPL_H 27 #define _SYS_AGGR_IMPL_H 28 29 #include <sys/types.h> 30 #include <sys/cred.h> 31 #include <sys/mac_ether.h> 32 #include <sys/mac_provider.h> 33 #include <sys/mac_client.h> 34 #include <sys/mac_client_priv.h> 35 #include <sys/aggr_lacp.h> 36 37 #ifdef __cplusplus 38 extern "C" { 39 #endif 40 41 #ifdef _KERNEL 42 43 #define AGGR_MINOR_CTL 1 /* control interface minor */ 44 45 /* flags for aggr_grp_modify() */ 46 #define AGGR_MODIFY_POLICY 0x01 47 #define AGGR_MODIFY_MAC 0x02 48 #define AGGR_MODIFY_LACP_MODE 0x04 49 #define AGGR_MODIFY_LACP_TIMER 0x08 50 51 /* 52 * Possible value of aggr_rseudo_rx_ring_t.arr_flags. Set when the ring entry 53 * in the pseudo RX group is used. 54 */ 55 #define MAC_PSEUDO_RING_INUSE 0x01 56 57 typedef struct aggr_unicst_addr_s { 58 uint8_t aua_addr[ETHERADDRL]; 59 struct aggr_unicst_addr_s *aua_next; 60 } aggr_unicst_addr_t; 61 62 typedef struct aggr_pseudo_rx_ring_s { 63 mac_ring_handle_t arr_rh; /* filled in by aggr_fill_ring() */ 64 struct aggr_port_s *arr_port; 65 mac_ring_handle_t arr_hw_rh; 66 uint_t arr_flags; 67 uint64_t arr_gen; 68 } aggr_pseudo_rx_ring_t; 69 70 typedef struct aggr_pseudo_rx_group_s { 71 struct aggr_grp_s *arg_grp; /* filled in by aggr_fill_group() */ 72 mac_group_handle_t arg_gh; /* filled in by aggr_fill_group() */ 73 aggr_unicst_addr_t *arg_macaddr; 74 aggr_pseudo_rx_ring_t arg_rings[MAX_RINGS_PER_GROUP]; 75 uint_t arg_ring_cnt; 76 } aggr_pseudo_rx_group_t; 77 78 /* 79 * A link aggregation MAC port. 80 * Note that lp_next is protected by the lg_lock of the group the 81 * port is part of. 82 */ 83 typedef struct aggr_port_s { 84 struct aggr_port_s *lp_next; 85 struct aggr_grp_s *lp_grp; /* back ptr to group */ 86 datalink_id_t lp_linkid; 87 uint16_t lp_portid; 88 uint8_t lp_addr[ETHERADDRL]; /* port MAC address */ 89 uint32_t lp_refs; /* refcount */ 90 aggr_port_state_t lp_state; 91 uint32_t lp_started : 1, 92 lp_tx_enabled : 1, 93 lp_collector_enabled : 1, 94 lp_promisc_on : 1, 95 lp_no_link_update : 1, 96 lp_grp_added : 1, 97 lp_closing : 1, 98 lp_pad_bits : 25; 99 mac_handle_t lp_mh; 100 mac_client_handle_t lp_mch; 101 const mac_info_t *lp_mip; 102 mac_notify_handle_t lp_mnh; 103 uint_t lp_tx_idx; /* idx in group's tx array */ 104 uint64_t lp_ifspeed; 105 link_state_t lp_link_state; 106 link_duplex_t lp_link_duplex; 107 uint64_t lp_stat[MAC_NSTAT]; 108 uint64_t lp_ether_stat[ETHER_NSTAT]; 109 aggr_lacp_port_t lp_lacp; /* LACP state */ 110 lacp_stats_t lp_lacp_stats; 111 uint32_t lp_margin; 112 mac_promisc_handle_t lp_mphp; 113 mac_unicast_handle_t lp_mah; 114 115 /* List of non-primary addresses that requires promiscous mode set */ 116 aggr_unicst_addr_t *lp_prom_addr; 117 /* handle of the underlying HW RX group */ 118 mac_group_handle_t lp_hwgh; 119 } aggr_port_t; 120 121 /* 122 * A link aggregation group. 123 * 124 * The following per-group flags are defined: 125 * 126 * - lg_addr_fixed: set when the MAC address has been explicitely set 127 * when the group was created, or by a m_unicst_set() request. 128 * If this flag is not set, the MAC address of the group will be 129 * set to the first port that is added to the group. 130 * 131 * - lg_add_set: used only when lg_addr_fixed is not set. Captures whether 132 * the MAC address was initialized according to the members of the group. 133 * When set, the lg_port field points to the port from which the 134 * MAC address was initialized. 135 * 136 */ 137 typedef struct aggr_grp_s { 138 datalink_id_t lg_linkid; 139 uint16_t lg_key; /* key (group port number) */ 140 uint32_t lg_refs; /* refcount */ 141 uint16_t lg_nports; /* number of MAC ports */ 142 uint8_t lg_addr[ETHERADDRL]; /* group MAC address */ 143 uint16_t 144 lg_closing : 1, 145 lg_addr_fixed : 1, /* fixed MAC address? */ 146 lg_started : 1, /* group started? */ 147 lg_promisc : 1, /* in promiscuous mode? */ 148 lg_zcopy : 1, 149 lg_vlan : 1, 150 lg_force : 1, 151 lg_lso : 1, 152 lg_pad_bits : 8; 153 aggr_port_t *lg_ports; /* list of configured ports */ 154 aggr_port_t *lg_mac_addr_port; 155 mac_handle_t lg_mh; 156 zoneid_t lg_zoneid; 157 uint_t lg_nattached_ports; 158 krwlock_t lg_tx_lock; 159 uint_t lg_ntx_ports; 160 aggr_port_t **lg_tx_ports; /* array of tx ports */ 161 uint_t lg_tx_ports_size; /* size of lg_tx_ports */ 162 uint32_t lg_tx_policy; /* outbound policy */ 163 uint8_t lg_mac_tx_policy; 164 uint64_t lg_ifspeed; 165 link_state_t lg_link_state; 166 link_duplex_t lg_link_duplex; 167 uint64_t lg_stat[MAC_NSTAT]; 168 uint64_t lg_ether_stat[ETHER_NSTAT]; 169 aggr_lacp_mode_t lg_lacp_mode; /* off, active, or passive */ 170 Agg_t aggr; /* 802.3ad data */ 171 uint32_t lg_hcksum_txflags; 172 uint_t lg_max_sdu; 173 uint32_t lg_margin; 174 mac_capab_lso_t lg_cap_lso; 175 176 /* 177 * The following fields are used by the LACP packets processing. 178 * Specifically, as the LACP packets processing is not performance 179 * critical, all LACP packets will be handled by a dedicated thread 180 * instead of in the mac_rx() call. This is to avoid the dead lock 181 * with mac_unicast_remove(), which holding the mac perimeter of the 182 * aggr, and wait for the mr_refcnt of the RX ring to drop to zero. 183 */ 184 kmutex_t lg_lacp_lock; 185 kcondvar_t lg_lacp_cv; 186 mblk_t *lg_lacp_head; 187 mblk_t *lg_lacp_tail; 188 kthread_t *lg_lacp_rx_thread; 189 boolean_t lg_lacp_done; 190 aggr_pseudo_rx_group_t lg_rx_group; 191 192 /* 193 * The following fields are used by aggr to wait for all the 194 * aggr_port_notify_cb() and aggr_port_timer_thread() to finish 195 * before it calls mac_unregister() when the aggr is deleted. 196 */ 197 kmutex_t lg_port_lock; 198 kcondvar_t lg_port_cv; 199 int lg_port_ref; 200 } aggr_grp_t; 201 202 #define AGGR_GRP_REFHOLD(grp) { \ 203 atomic_add_32(&(grp)->lg_refs, 1); \ 204 ASSERT((grp)->lg_refs != 0); \ 205 } 206 207 #define AGGR_GRP_REFRELE(grp) { \ 208 ASSERT((grp)->lg_refs != 0); \ 209 membar_exit(); \ 210 if (atomic_add_32_nv(&(grp)->lg_refs, -1) == 0) \ 211 aggr_grp_free(grp); \ 212 } 213 214 #define AGGR_PORT_REFHOLD(port) { \ 215 atomic_add_32(&(port)->lp_refs, 1); \ 216 ASSERT((port)->lp_refs != 0); \ 217 } 218 219 #define AGGR_PORT_REFRELE(port) { \ 220 ASSERT((port)->lp_refs != 0); \ 221 membar_exit(); \ 222 if (atomic_add_32_nv(&(port)->lp_refs, -1) == 0) \ 223 aggr_port_free(port); \ 224 } 225 226 extern dev_info_t *aggr_dip; 227 extern int aggr_ioc_init(void); 228 extern void aggr_ioc_fini(void); 229 230 typedef int (*aggr_grp_info_new_grp_fn_t)(void *, datalink_id_t, uint32_t, 231 uchar_t *, boolean_t, boolean_t, uint32_t, uint32_t, aggr_lacp_mode_t, 232 aggr_lacp_timer_t); 233 typedef int (*aggr_grp_info_new_port_fn_t)(void *, datalink_id_t, uchar_t *, 234 aggr_port_state_t, aggr_lacp_state_t *); 235 236 extern void aggr_grp_init(void); 237 extern void aggr_grp_fini(void); 238 extern int aggr_grp_create(datalink_id_t, uint32_t, uint_t, laioc_port_t *, 239 uint32_t, boolean_t, boolean_t, uchar_t *, aggr_lacp_mode_t, 240 aggr_lacp_timer_t, cred_t *); 241 extern int aggr_grp_delete(datalink_id_t, cred_t *); 242 extern void aggr_grp_free(aggr_grp_t *); 243 244 extern int aggr_grp_info(datalink_id_t, void *, aggr_grp_info_new_grp_fn_t, 245 aggr_grp_info_new_port_fn_t, cred_t *); 246 extern void aggr_grp_notify(aggr_grp_t *, uint32_t); 247 extern boolean_t aggr_grp_attach_port(aggr_grp_t *, aggr_port_t *); 248 extern boolean_t aggr_grp_detach_port(aggr_grp_t *, aggr_port_t *); 249 extern void aggr_grp_port_mac_changed(aggr_grp_t *, aggr_port_t *, 250 boolean_t *, boolean_t *); 251 extern int aggr_grp_add_ports(datalink_id_t, uint_t, boolean_t, 252 laioc_port_t *); 253 extern int aggr_grp_rem_ports(datalink_id_t, uint_t, laioc_port_t *); 254 extern boolean_t aggr_grp_update_ports_mac(aggr_grp_t *); 255 extern int aggr_grp_modify(datalink_id_t, uint8_t, uint32_t, boolean_t, 256 const uchar_t *, aggr_lacp_mode_t, aggr_lacp_timer_t); 257 extern void aggr_grp_multicst_port(aggr_port_t *, boolean_t); 258 extern uint_t aggr_grp_count(void); 259 260 extern void aggr_port_init(void); 261 extern void aggr_port_fini(void); 262 extern int aggr_port_create(aggr_grp_t *, const datalink_id_t, boolean_t, 263 aggr_port_t **); 264 extern void aggr_port_delete(aggr_port_t *); 265 extern void aggr_port_free(aggr_port_t *); 266 extern int aggr_port_start(aggr_port_t *); 267 extern void aggr_port_stop(aggr_port_t *); 268 extern int aggr_port_promisc(aggr_port_t *, boolean_t); 269 extern int aggr_port_unicst(aggr_port_t *); 270 extern int aggr_port_multicst(void *, boolean_t, const uint8_t *); 271 extern uint64_t aggr_port_stat(aggr_port_t *, uint_t); 272 extern boolean_t aggr_port_notify_link(aggr_grp_t *, aggr_port_t *); 273 extern void aggr_port_init_callbacks(aggr_port_t *); 274 275 extern void aggr_recv_cb(void *, mac_resource_handle_t, mblk_t *, boolean_t); 276 277 extern mblk_t *aggr_m_tx(void *, mblk_t *); 278 extern void aggr_send_port_enable(aggr_port_t *); 279 extern void aggr_send_port_disable(aggr_port_t *); 280 extern void aggr_send_update_policy(aggr_grp_t *, uint32_t); 281 282 extern void aggr_lacp_init(void); 283 extern void aggr_lacp_fini(void); 284 extern void aggr_lacp_init_port(aggr_port_t *); 285 extern void aggr_lacp_init_grp(aggr_grp_t *); 286 extern void aggr_lacp_set_mode(aggr_grp_t *, aggr_lacp_mode_t, 287 aggr_lacp_timer_t); 288 extern void aggr_lacp_update_mode(aggr_grp_t *, aggr_lacp_mode_t); 289 extern void aggr_lacp_update_timer(aggr_grp_t *, aggr_lacp_timer_t); 290 extern void aggr_lacp_rx_enqueue(aggr_port_t *, mblk_t *); 291 extern void aggr_lacp_port_attached(aggr_port_t *); 292 extern void aggr_lacp_port_detached(aggr_port_t *); 293 extern void aggr_port_lacp_set_mode(aggr_grp_t *, aggr_port_t *); 294 295 extern void aggr_lacp_rx_thread(void *); 296 extern void aggr_recv_lacp(aggr_port_t *, mac_resource_handle_t, mblk_t *); 297 298 extern void aggr_grp_port_hold(aggr_port_t *); 299 extern void aggr_grp_port_rele(aggr_port_t *); 300 extern void aggr_grp_port_wait(aggr_grp_t *); 301 302 extern int aggr_port_addmac(aggr_port_t *, const uint8_t *); 303 extern void aggr_port_remmac(aggr_port_t *, const uint8_t *); 304 305 #endif /* _KERNEL */ 306 307 #ifdef __cplusplus 308 } 309 #endif 310 311 #endif /* _SYS_AGGR_IMPL_H */ 312