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