aggr_impl.h revision 10616:3be00c4a6835
138581Sobrien/*
238581Sobrien * CDDL HEADER START
338581Sobrien *
438581Sobrien * The contents of this file are subject to the terms of the
538581Sobrien * Common Development and Distribution License (the "License").
650479Speter * You may not use this file except in compliance with the License.
738581Sobrien *
880029Sobrien * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
980029Sobrien * or http://www.opensolaris.org/os/licensing.
1080029Sobrien * See the License for the specific language governing permissions
1180029Sobrien * and limitations under the License.
1238581Sobrien *
1380029Sobrien * When distributing Covered Code, include this CDDL HEADER in each
14136910Sru * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1580029Sobrien * If applicable, add the following below this CDDL HEADER, with the
16174306Sobrien * fields enclosed by brackets "[]" replaced with your own identifying
1738581Sobrien * information: Portions Copyright [yyyy] [name of copyright owner]
1880029Sobrien *
1980029Sobrien * CDDL HEADER END
2038581Sobrien */
2138581Sobrien/*
22174306Sobrien * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23174306Sobrien * Use is subject to license terms.
2438581Sobrien */
2582825Sobrien
2682825Sobrien#ifndef	_SYS_AGGR_IMPL_H
2780029Sobrien#define	_SYS_AGGR_IMPL_H
2838581Sobrien
2982825Sobrien#include <sys/types.h>
3038581Sobrien#include <sys/cred.h>
31174306Sobrien#include <sys/mac_ether.h>
32174306Sobrien#include <sys/mac_provider.h>
33174306Sobrien#include <sys/mac_client.h>
34174306Sobrien#include <sys/mac_client_priv.h>
35174306Sobrien#include <sys/aggr_lacp.h>
3638581Sobrien
37#ifdef	__cplusplus
38extern "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
57typedef 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
62typedef 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
70typedef 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 */
83typedef 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 */
137typedef 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
226extern dev_info_t *aggr_dip;
227extern int aggr_ioc_init(void);
228extern void aggr_ioc_fini(void);
229
230typedef 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);
233typedef int (*aggr_grp_info_new_port_fn_t)(void *, datalink_id_t, uchar_t *,
234    aggr_port_state_t, aggr_lacp_state_t *);
235
236extern void aggr_grp_init(void);
237extern void aggr_grp_fini(void);
238extern 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 *);
241extern int aggr_grp_delete(datalink_id_t, cred_t *);
242extern void aggr_grp_free(aggr_grp_t *);
243
244extern 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 *);
246extern void aggr_grp_notify(aggr_grp_t *, uint32_t);
247extern boolean_t aggr_grp_attach_port(aggr_grp_t *, aggr_port_t *);
248extern boolean_t aggr_grp_detach_port(aggr_grp_t *, aggr_port_t *);
249extern void aggr_grp_port_mac_changed(aggr_grp_t *, aggr_port_t *,
250    boolean_t *, boolean_t *);
251extern int aggr_grp_add_ports(datalink_id_t, uint_t, boolean_t,
252    laioc_port_t *);
253extern int aggr_grp_rem_ports(datalink_id_t, uint_t, laioc_port_t *);
254extern boolean_t aggr_grp_update_ports_mac(aggr_grp_t *);
255extern 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);
257extern void aggr_grp_multicst_port(aggr_port_t *, boolean_t);
258extern uint_t aggr_grp_count(void);
259
260extern void aggr_port_init(void);
261extern void aggr_port_fini(void);
262extern int aggr_port_create(aggr_grp_t *, const datalink_id_t, boolean_t,
263    aggr_port_t **);
264extern void aggr_port_delete(aggr_port_t *);
265extern void aggr_port_free(aggr_port_t *);
266extern int aggr_port_start(aggr_port_t *);
267extern void aggr_port_stop(aggr_port_t *);
268extern int aggr_port_promisc(aggr_port_t *, boolean_t);
269extern int aggr_port_unicst(aggr_port_t *);
270extern int aggr_port_multicst(void *, boolean_t, const uint8_t *);
271extern uint64_t aggr_port_stat(aggr_port_t *, uint_t);
272extern boolean_t aggr_port_notify_link(aggr_grp_t *, aggr_port_t *);
273extern void aggr_port_init_callbacks(aggr_port_t *);
274
275extern void aggr_recv_cb(void *, mac_resource_handle_t, mblk_t *, boolean_t);
276
277extern mblk_t *aggr_m_tx(void *, mblk_t *);
278extern void aggr_send_port_enable(aggr_port_t *);
279extern void aggr_send_port_disable(aggr_port_t *);
280extern void aggr_send_update_policy(aggr_grp_t *, uint32_t);
281
282extern void aggr_lacp_init(void);
283extern void aggr_lacp_fini(void);
284extern void aggr_lacp_init_port(aggr_port_t *);
285extern void aggr_lacp_init_grp(aggr_grp_t *);
286extern void aggr_lacp_set_mode(aggr_grp_t *, aggr_lacp_mode_t,
287    aggr_lacp_timer_t);
288extern void aggr_lacp_update_mode(aggr_grp_t *, aggr_lacp_mode_t);
289extern void aggr_lacp_update_timer(aggr_grp_t *, aggr_lacp_timer_t);
290extern void aggr_lacp_rx_enqueue(aggr_port_t *, mblk_t *);
291extern void aggr_lacp_port_attached(aggr_port_t *);
292extern void aggr_lacp_port_detached(aggr_port_t *);
293extern void aggr_port_lacp_set_mode(aggr_grp_t *, aggr_port_t *);
294
295extern void aggr_lacp_rx_thread(void *);
296extern void aggr_recv_lacp(aggr_port_t *, mac_resource_handle_t, mblk_t *);
297
298extern void aggr_grp_port_hold(aggr_port_t *);
299extern void aggr_grp_port_rele(aggr_port_t *);
300extern void aggr_grp_port_wait(aggr_grp_t *);
301
302extern int aggr_port_addmac(aggr_port_t *, const uint8_t *);
303extern 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