Home | History | Annotate | Download | only in sys
      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