xref: /openbsd/sys/net/trunklacp.h (revision a14b8f16)
1*a14b8f16Smpf /*	$OpenBSD: trunklacp.h,v 1.1 2008/06/15 06:56:09 mpf Exp $	*/
2*a14b8f16Smpf /*	$NetBSD: ieee8023ad_impl.h,v 1.2 2005/12/10 23:21:39 elad Exp $	*/
3*a14b8f16Smpf 
4*a14b8f16Smpf /*
5*a14b8f16Smpf  * Copyright (c)2005 YAMAMOTO Takashi,
6*a14b8f16Smpf  * All rights reserved.
7*a14b8f16Smpf  *
8*a14b8f16Smpf  * Redistribution and use in source and binary forms, with or without
9*a14b8f16Smpf  * modification, are permitted provided that the following conditions
10*a14b8f16Smpf  * are met:
11*a14b8f16Smpf  * 1. Redistributions of source code must retain the above copyright
12*a14b8f16Smpf  *    notice, this list of conditions and the following disclaimer.
13*a14b8f16Smpf  * 2. Redistributions in binary form must reproduce the above copyright
14*a14b8f16Smpf  *    notice, this list of conditions and the following disclaimer in the
15*a14b8f16Smpf  *    documentation and/or other materials provided with the distribution.
16*a14b8f16Smpf  *
17*a14b8f16Smpf  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18*a14b8f16Smpf  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19*a14b8f16Smpf  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20*a14b8f16Smpf  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21*a14b8f16Smpf  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*a14b8f16Smpf  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23*a14b8f16Smpf  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24*a14b8f16Smpf  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25*a14b8f16Smpf  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26*a14b8f16Smpf  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27*a14b8f16Smpf  * SUCH DAMAGE.
28*a14b8f16Smpf  *
29*a14b8f16Smpf  * $FreeBSD: src/sys/net/ieee8023ad_lacp.h,v 1.11 2008/03/17 01:26:44 thompsa Exp $
30*a14b8f16Smpf  */
31*a14b8f16Smpf 
32*a14b8f16Smpf /*
33*a14b8f16Smpf  * IEEE802.3ad LACP
34*a14b8f16Smpf  *
35*a14b8f16Smpf  * implementation details.
36*a14b8f16Smpf  */
37*a14b8f16Smpf 
38*a14b8f16Smpf #define	LACP_TIMER_CURRENT_WHILE	0
39*a14b8f16Smpf #define	LACP_TIMER_PERIODIC		1
40*a14b8f16Smpf #define	LACP_TIMER_WAIT_WHILE		2
41*a14b8f16Smpf #define	LACP_NTIMER			3
42*a14b8f16Smpf 
43*a14b8f16Smpf #define	LACP_TIMER_ARM(port, timer, val) \
44*a14b8f16Smpf 	(port)->lp_timer[(timer)] = (val)
45*a14b8f16Smpf #define	LACP_TIMER_DISARM(port, timer) \
46*a14b8f16Smpf 	(port)->lp_timer[(timer)] = 0
47*a14b8f16Smpf #define	LACP_TIMER_ISARMED(port, timer) \
48*a14b8f16Smpf 	((port)->lp_timer[(timer)] > 0)
49*a14b8f16Smpf 
50*a14b8f16Smpf /*
51*a14b8f16Smpf  * IEEE802.3ad LACP
52*a14b8f16Smpf  *
53*a14b8f16Smpf  * protocol definitions.
54*a14b8f16Smpf  */
55*a14b8f16Smpf 
56*a14b8f16Smpf #define	LACP_STATE_ACTIVITY	(1<<0)
57*a14b8f16Smpf #define	LACP_STATE_TIMEOUT	(1<<1)
58*a14b8f16Smpf #define	LACP_STATE_AGGREGATION	(1<<2)
59*a14b8f16Smpf #define	LACP_STATE_SYNC		(1<<3)
60*a14b8f16Smpf #define	LACP_STATE_COLLECTING	(1<<4)
61*a14b8f16Smpf #define	LACP_STATE_DISTRIBUTING	(1<<5)
62*a14b8f16Smpf #define	LACP_STATE_DEFAULTED	(1<<6)
63*a14b8f16Smpf #define	LACP_STATE_EXPIRED	(1<<7)
64*a14b8f16Smpf 
65*a14b8f16Smpf #define	LACP_PORT_NTT		0x00000001
66*a14b8f16Smpf #define	LACP_PORT_MARK		0x00000002
67*a14b8f16Smpf 
68*a14b8f16Smpf #define	LACP_STATE_BITS		\
69*a14b8f16Smpf 	"\020"			\
70*a14b8f16Smpf 	"\001ACTIVITY"		\
71*a14b8f16Smpf 	"\002TIMEOUT"		\
72*a14b8f16Smpf 	"\003AGGREGATION"	\
73*a14b8f16Smpf 	"\004SYNC"		\
74*a14b8f16Smpf 	"\005COLLECTING"	\
75*a14b8f16Smpf 	"\006DISTRIBUTING"	\
76*a14b8f16Smpf 	"\007DEFAULTED"		\
77*a14b8f16Smpf 	"\010EXPIRED"
78*a14b8f16Smpf 
79*a14b8f16Smpf /*
80*a14b8f16Smpf  * IEEE802.3 slow protocols
81*a14b8f16Smpf  *
82*a14b8f16Smpf  * protocol (on-wire) definitions.
83*a14b8f16Smpf  *
84*a14b8f16Smpf  * XXX should be elsewhere.
85*a14b8f16Smpf  */
86*a14b8f16Smpf 
87*a14b8f16Smpf #define	SLOWPROTOCOLS_SUBTYPE_LACP	1
88*a14b8f16Smpf #define	SLOWPROTOCOLS_SUBTYPE_MARKER	2
89*a14b8f16Smpf 
90*a14b8f16Smpf struct slowprothdr {
91*a14b8f16Smpf 	uint8_t		sph_subtype;
92*a14b8f16Smpf 	uint8_t		sph_version;
93*a14b8f16Smpf } __packed;
94*a14b8f16Smpf 
95*a14b8f16Smpf /*
96*a14b8f16Smpf  * TLV on-wire structure.
97*a14b8f16Smpf  */
98*a14b8f16Smpf 
99*a14b8f16Smpf struct tlvhdr {
100*a14b8f16Smpf 	uint8_t		tlv_type;
101*a14b8f16Smpf 	uint8_t		tlv_length;
102*a14b8f16Smpf 	/* uint8_t tlv_value[]; */
103*a14b8f16Smpf } __packed;
104*a14b8f16Smpf 
105*a14b8f16Smpf /*
106*a14b8f16Smpf  * ... and our implementation.
107*a14b8f16Smpf  */
108*a14b8f16Smpf 
109*a14b8f16Smpf #define	TLV_SET(tlv, type, length) \
110*a14b8f16Smpf 	do { \
111*a14b8f16Smpf 		(tlv)->tlv_type = (type); \
112*a14b8f16Smpf 		(tlv)->tlv_length = sizeof(*tlv) + (length); \
113*a14b8f16Smpf 	} while (/*CONSTCOND*/0)
114*a14b8f16Smpf 
115*a14b8f16Smpf struct tlv_template {
116*a14b8f16Smpf 	uint8_t			tmpl_type;
117*a14b8f16Smpf 	uint8_t			tmpl_length;
118*a14b8f16Smpf };
119*a14b8f16Smpf 
120*a14b8f16Smpf struct lacp_systemid {
121*a14b8f16Smpf 	uint16_t		lsi_prio;
122*a14b8f16Smpf 	uint8_t			lsi_mac[6];
123*a14b8f16Smpf } __packed;
124*a14b8f16Smpf 
125*a14b8f16Smpf struct lacp_portid {
126*a14b8f16Smpf 	uint16_t		lpi_prio;
127*a14b8f16Smpf 	uint16_t		lpi_portno;
128*a14b8f16Smpf } __packed;
129*a14b8f16Smpf 
130*a14b8f16Smpf struct lacp_peerinfo {
131*a14b8f16Smpf 	struct lacp_systemid	lip_systemid;
132*a14b8f16Smpf 	uint16_t		lip_key;
133*a14b8f16Smpf 	struct lacp_portid	lip_portid;
134*a14b8f16Smpf 	uint8_t			lip_state;
135*a14b8f16Smpf 	uint8_t			lip_resv[3];
136*a14b8f16Smpf } __packed;
137*a14b8f16Smpf 
138*a14b8f16Smpf struct lacp_collectorinfo {
139*a14b8f16Smpf 	uint16_t		lci_maxdelay;
140*a14b8f16Smpf 	uint8_t			lci_resv[12];
141*a14b8f16Smpf } __packed;
142*a14b8f16Smpf 
143*a14b8f16Smpf struct lacpdu {
144*a14b8f16Smpf 	struct ether_header	ldu_eh;
145*a14b8f16Smpf 	struct slowprothdr	ldu_sph;
146*a14b8f16Smpf 
147*a14b8f16Smpf 	struct tlvhdr		ldu_tlv_actor;
148*a14b8f16Smpf 	struct lacp_peerinfo	ldu_actor;
149*a14b8f16Smpf 	struct tlvhdr		ldu_tlv_partner;
150*a14b8f16Smpf 	struct lacp_peerinfo	ldu_partner;
151*a14b8f16Smpf 	struct tlvhdr		ldu_tlv_collector;
152*a14b8f16Smpf 	struct lacp_collectorinfo ldu_collector;
153*a14b8f16Smpf 	struct tlvhdr		ldu_tlv_term;
154*a14b8f16Smpf 	uint8_t			ldu_resv[50];
155*a14b8f16Smpf } __packed;
156*a14b8f16Smpf 
157*a14b8f16Smpf /*
158*a14b8f16Smpf  * IEEE802.3ad marker protocol
159*a14b8f16Smpf  *
160*a14b8f16Smpf  * protocol (on-wire) definitions.
161*a14b8f16Smpf  */
162*a14b8f16Smpf struct lacp_markerinfo {
163*a14b8f16Smpf 	uint16_t		mi_rq_port;
164*a14b8f16Smpf 	uint8_t			mi_rq_system[ETHER_ADDR_LEN];
165*a14b8f16Smpf 	uint32_t		mi_rq_xid;
166*a14b8f16Smpf 	uint8_t			mi_pad[2];
167*a14b8f16Smpf } __packed;
168*a14b8f16Smpf 
169*a14b8f16Smpf struct markerdu {
170*a14b8f16Smpf 	struct ether_header	mdu_eh;
171*a14b8f16Smpf 	struct slowprothdr	mdu_sph;
172*a14b8f16Smpf 
173*a14b8f16Smpf 	struct tlvhdr		mdu_tlv;
174*a14b8f16Smpf 	struct lacp_markerinfo	mdu_info;
175*a14b8f16Smpf 	struct tlvhdr		mdu_tlv_term;
176*a14b8f16Smpf 	uint8_t			mdu_resv[90];
177*a14b8f16Smpf } __packed;
178*a14b8f16Smpf 
179*a14b8f16Smpf #define	MARKER_TYPE_INFO	0x01
180*a14b8f16Smpf #define	MARKER_TYPE_RESPONSE	0x02
181*a14b8f16Smpf 
182*a14b8f16Smpf enum lacp_selected {
183*a14b8f16Smpf 	LACP_UNSELECTED,
184*a14b8f16Smpf 	LACP_STANDBY,	/* not used in this implementation */
185*a14b8f16Smpf 	LACP_SELECTED,
186*a14b8f16Smpf };
187*a14b8f16Smpf 
188*a14b8f16Smpf enum lacp_mux_state {
189*a14b8f16Smpf 	LACP_MUX_DETACHED,
190*a14b8f16Smpf 	LACP_MUX_WAITING,
191*a14b8f16Smpf 	LACP_MUX_ATTACHED,
192*a14b8f16Smpf 	LACP_MUX_COLLECTING,
193*a14b8f16Smpf 	LACP_MUX_DISTRIBUTING,
194*a14b8f16Smpf };
195*a14b8f16Smpf 
196*a14b8f16Smpf #define	LACP_MAX_PORTS		32
197*a14b8f16Smpf 
198*a14b8f16Smpf struct lacp_portmap {
199*a14b8f16Smpf 	int			pm_count;
200*a14b8f16Smpf 	struct lacp_port	*pm_map[LACP_MAX_PORTS];
201*a14b8f16Smpf };
202*a14b8f16Smpf 
203*a14b8f16Smpf struct lacp_port {
204*a14b8f16Smpf 	TAILQ_ENTRY(lacp_port)	lp_dist_q;
205*a14b8f16Smpf 	LIST_ENTRY(lacp_port)	lp_next;
206*a14b8f16Smpf 	struct lacp_softc	*lp_lsc;
207*a14b8f16Smpf 	struct trunk_port	*lp_trunk;
208*a14b8f16Smpf 	struct ifnet		*lp_ifp;
209*a14b8f16Smpf 	struct lacp_peerinfo	lp_partner;
210*a14b8f16Smpf 	struct lacp_peerinfo	lp_actor;
211*a14b8f16Smpf 	struct lacp_markerinfo	lp_marker;
212*a14b8f16Smpf #define	lp_state	lp_actor.lip_state
213*a14b8f16Smpf #define	lp_key		lp_actor.lip_key
214*a14b8f16Smpf #define	lp_systemid	lp_actor.lip_systemid
215*a14b8f16Smpf 	struct timeval		lp_last_lacpdu;
216*a14b8f16Smpf 	int			lp_lacpdu_sent;
217*a14b8f16Smpf 	enum lacp_mux_state	lp_mux_state;
218*a14b8f16Smpf 	enum lacp_selected	lp_selected;
219*a14b8f16Smpf 	int			lp_flags;
220*a14b8f16Smpf 	u_int			lp_media; /* XXX redundant */
221*a14b8f16Smpf 	int			lp_timer[LACP_NTIMER];
222*a14b8f16Smpf 	struct ifmultiaddr	*lp_ifma;
223*a14b8f16Smpf 
224*a14b8f16Smpf 	struct lacp_aggregator	*lp_aggregator;
225*a14b8f16Smpf };
226*a14b8f16Smpf 
227*a14b8f16Smpf struct lacp_aggregator {
228*a14b8f16Smpf 	TAILQ_ENTRY(lacp_aggregator)	la_q;
229*a14b8f16Smpf 	int			la_refcnt; /* num of ports which selected us */
230*a14b8f16Smpf 	int			la_nports; /* num of distributing ports  */
231*a14b8f16Smpf 	TAILQ_HEAD(, lacp_port)	la_ports; /* distributing ports */
232*a14b8f16Smpf 	struct lacp_peerinfo	la_partner;
233*a14b8f16Smpf 	struct lacp_peerinfo	la_actor;
234*a14b8f16Smpf 	int			la_pending; /* number of ports in wait_while */
235*a14b8f16Smpf };
236*a14b8f16Smpf 
237*a14b8f16Smpf struct lacp_softc {
238*a14b8f16Smpf 	struct trunk_softc	*lsc_softc;
239*a14b8f16Smpf 	struct lacp_aggregator	*lsc_active_aggregator;
240*a14b8f16Smpf 	TAILQ_HEAD(, lacp_aggregator) lsc_aggregators;
241*a14b8f16Smpf 	int		lsc_suppress_distributing;
242*a14b8f16Smpf 	struct timeout		lsc_transit_callout;
243*a14b8f16Smpf 	struct timeout		lsc_callout;
244*a14b8f16Smpf 	LIST_HEAD(, lacp_port)	lsc_ports;
245*a14b8f16Smpf 	struct lacp_portmap	lsc_pmap[2];
246*a14b8f16Smpf 	volatile u_int		lsc_activemap;
247*a14b8f16Smpf 	u_int32_t		lsc_hashkey;
248*a14b8f16Smpf };
249*a14b8f16Smpf 
250*a14b8f16Smpf #define	LACP_TYPE_ACTORINFO	1
251*a14b8f16Smpf #define	LACP_TYPE_PARTNERINFO	2
252*a14b8f16Smpf #define	LACP_TYPE_COLLECTORINFO	3
253*a14b8f16Smpf 
254*a14b8f16Smpf /* timeout values (in sec) */
255*a14b8f16Smpf #define	LACP_FAST_PERIODIC_TIME		(1)
256*a14b8f16Smpf #define	LACP_SLOW_PERIODIC_TIME		(30)
257*a14b8f16Smpf #define	LACP_SHORT_TIMEOUT_TIME		(3 * LACP_FAST_PERIODIC_TIME)
258*a14b8f16Smpf #define	LACP_LONG_TIMEOUT_TIME		(3 * LACP_SLOW_PERIODIC_TIME)
259*a14b8f16Smpf #define	LACP_CHURN_DETECTION_TIME	(60)
260*a14b8f16Smpf #define	LACP_AGGREGATE_WAIT_TIME	(2)
261*a14b8f16Smpf #define	LACP_TRANSIT_DELAY		3000	/* in msec */
262*a14b8f16Smpf 
263*a14b8f16Smpf #define	LACP_STATE_EQ(s1, s2, mask)	\
264*a14b8f16Smpf 	((((s1) ^ (s2)) & (mask)) == 0)
265*a14b8f16Smpf 
266*a14b8f16Smpf #define	LACP_SYS_PRI(peer)	(peer).lip_systemid.lsi_prio
267*a14b8f16Smpf 
268*a14b8f16Smpf #define	LACP_PORT(_lp)	((struct lacp_port *)(_lp)->tp_psc)
269*a14b8f16Smpf #define	LACP_SOFTC(_sc)	((struct lacp_softc *)(_sc)->tr_psc)
270*a14b8f16Smpf 
271*a14b8f16Smpf #define LACP_LOCK_INIT(_lsc)		mtx_init(&(_lsc)->lsc_mtx, \
272*a14b8f16Smpf 					    "lacp mtx", NULL, MTX_DEF)
273*a14b8f16Smpf #define LACP_LOCK_DESTROY(_lsc)		mtx_destroy(&(_lsc)->lsc_mtx)
274*a14b8f16Smpf #define LACP_LOCK(_lsc)			mtx_lock(&(_lsc)->lsc_mtx)
275*a14b8f16Smpf #define LACP_UNLOCK(_lsc)		mtx_unlock(&(_lsc)->lsc_mtx)
276*a14b8f16Smpf #define LACP_LOCK_ASSERT(_lsc)		mtx_assert(&(_lsc)->lsc_mtx, MA_OWNED)
277*a14b8f16Smpf 
278*a14b8f16Smpf struct mbuf	*lacp_input(struct trunk_port *, struct mbuf *);
279*a14b8f16Smpf struct trunk_port *lacp_select_tx_port(struct trunk_softc *, struct mbuf *);
280*a14b8f16Smpf int		lacp_attach(struct trunk_softc *);
281*a14b8f16Smpf int		lacp_detach(struct trunk_softc *);
282*a14b8f16Smpf void		lacp_init(struct trunk_softc *);
283*a14b8f16Smpf void		lacp_stop(struct trunk_softc *);
284*a14b8f16Smpf int		lacp_port_create(struct trunk_port *);
285*a14b8f16Smpf void		lacp_port_destroy(struct trunk_port *);
286*a14b8f16Smpf void		lacp_linkstate(struct trunk_port *);
287*a14b8f16Smpf void		lacp_req(struct trunk_softc *, caddr_t);
288*a14b8f16Smpf void		lacp_portreq(struct trunk_port *, caddr_t);
289*a14b8f16Smpf 
290*a14b8f16Smpf static __inline int
291*a14b8f16Smpf lacp_isactive(struct trunk_port *lgp)
292*a14b8f16Smpf {
293*a14b8f16Smpf 	struct lacp_port *lp = LACP_PORT(lgp);
294*a14b8f16Smpf 	struct lacp_softc *lsc = lp->lp_lsc;
295*a14b8f16Smpf 	struct lacp_aggregator *la = lp->lp_aggregator;
296*a14b8f16Smpf 
297*a14b8f16Smpf 	/* This port is joined to the active aggregator */
298*a14b8f16Smpf 	if (la != NULL && la == lsc->lsc_active_aggregator)
299*a14b8f16Smpf 		return (1);
300*a14b8f16Smpf 
301*a14b8f16Smpf 	return (0);
302*a14b8f16Smpf }
303*a14b8f16Smpf 
304*a14b8f16Smpf static __inline int
305*a14b8f16Smpf lacp_iscollecting(struct trunk_port *lgp)
306*a14b8f16Smpf {
307*a14b8f16Smpf 	struct lacp_port *lp = LACP_PORT(lgp);
308*a14b8f16Smpf 
309*a14b8f16Smpf 	return ((lp->lp_state & LACP_STATE_COLLECTING) != 0);
310*a14b8f16Smpf }
311*a14b8f16Smpf 
312*a14b8f16Smpf static __inline int
313*a14b8f16Smpf lacp_isdistributing(struct trunk_port *lgp)
314*a14b8f16Smpf {
315*a14b8f16Smpf 	struct lacp_port *lp = LACP_PORT(lgp);
316*a14b8f16Smpf 
317*a14b8f16Smpf 	return ((lp->lp_state & LACP_STATE_DISTRIBUTING) != 0);
318*a14b8f16Smpf }
319*a14b8f16Smpf 
320*a14b8f16Smpf /* following constants don't include terminating NUL */
321*a14b8f16Smpf #define	LACP_MACSTR_MAX		(2*6 + 5)
322*a14b8f16Smpf #define	LACP_SYSTEMPRIOSTR_MAX	(4)
323*a14b8f16Smpf #define	LACP_SYSTEMIDSTR_MAX	(LACP_SYSTEMPRIOSTR_MAX + 1 + LACP_MACSTR_MAX)
324*a14b8f16Smpf #define	LACP_PORTPRIOSTR_MAX	(4)
325*a14b8f16Smpf #define	LACP_PORTNOSTR_MAX	(4)
326*a14b8f16Smpf #define	LACP_PORTIDSTR_MAX	(LACP_PORTPRIOSTR_MAX + 1 + LACP_PORTNOSTR_MAX)
327*a14b8f16Smpf #define	LACP_KEYSTR_MAX		(4)
328*a14b8f16Smpf #define	LACP_PARTNERSTR_MAX	\
329*a14b8f16Smpf 	(1 + LACP_SYSTEMIDSTR_MAX + 1 + LACP_KEYSTR_MAX + 1 \
330*a14b8f16Smpf 	+ LACP_PORTIDSTR_MAX + 1)
331*a14b8f16Smpf #define	LACP_LAGIDSTR_MAX	\
332*a14b8f16Smpf 	(1 + LACP_PARTNERSTR_MAX + 1 + LACP_PARTNERSTR_MAX + 1)
333*a14b8f16Smpf #define	LACP_STATESTR_MAX	(255) /* XXX */
334