xref: /netbsd-src/sys/net/lagg/if_lagg_lacp.c (revision a656d0edac216fd316b4c2448970ce285c0ccdb6)
1 /*	$NetBSD: if_lagg_lacp.c,v 1.43 2024/04/05 06:31:37 yamaguchi Exp $	*/
2 
3 /*-
4  * SPDX-License-Identifier: BSD-2-Clause-NetBSD
5  *
6  * Copyright (c)2005 YAMAMOTO Takashi,
7  * Copyright (c)2008 Andrew Thompson <thompsa@FreeBSD.org>
8  * Copyright (c)2021 Internet Initiative Japan, Inc.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: if_lagg_lacp.c,v 1.43 2024/04/05 06:31:37 yamaguchi Exp $");
35 
36 #ifdef _KERNEL_OPT
37 #include "opt_lagg.h"
38 #endif
39 
40 #include <sys/param.h>
41 #include <sys/types.h>
42 
43 #include <sys/evcnt.h>
44 #include <sys/kmem.h>
45 #include <sys/pcq.h>
46 #include <sys/pslist.h>
47 #include <sys/sysctl.h>
48 #include <sys/syslog.h>
49 #include <sys/workqueue.h>
50 
51 #include <net/if.h>
52 #include <net/if_dl.h>
53 #include <net/if_ether.h>
54 #include <net/if_media.h>
55 
56 #include <net/ether_slowprotocols.h>
57 
58 #include <net/lagg/if_lagg.h>
59 #include <net/lagg/if_laggproto.h>
60 #include <net/lagg/if_lagg_lacp.h>
61 
62 #define LACP_SYSTEMIDSTR_LEN	32
63 
64 enum {
65 	LACP_TIMER_CURRENT_WHILE = 0,
66 	LACP_TIMER_PERIODIC,
67 	LACP_TIMER_WAIT_WHILE,
68 	LACP_NTIMER
69 };
70 
71 enum {
72 	LACP_PTIMER_DISTRIBUTING = 0,
73 	LACP_NPTIMER
74 };
75 
76 enum lacp_selected {
77 	LACP_UNSELECTED,
78 	LACP_READY,
79 	LACP_STANDBY,
80 	LACP_SELECTED,
81 };
82 
83 enum lacp_mux_state {
84 	LACP_MUX_DETACHED,
85 	LACP_MUX_WAITING,
86 	LACP_MUX_STANDBY,
87 	LACP_MUX_ATTACHED,
88 	LACP_MUX_COLLECTING,
89 	LACP_MUX_DISTRIBUTING,
90 	LACP_MUX_INIT,
91 };
92 
93 struct lacp_aggregator_systemid {
94 	uint16_t	 sid_prio;
95 	uint16_t	 sid_key;
96 	uint8_t		 sid_mac[LACP_MAC_LEN];
97 };
98 
99 struct lacp_aggregator {
100 	TAILQ_ENTRY(lacp_aggregator)
101 			 la_q;
102 	LIST_HEAD(, lacp_port)
103 			 la_ports;
104 	ssize_t		 la_attached_port;
105 
106 	struct lacp_aggregator_systemid
107 			 la_sid;
108 };
109 
110 struct lacp_portinfo {
111 	uint8_t		 lpi_state;
112 	uint16_t	 lpi_portno;
113 #define LACP_PORTNO_NONE	0
114 	uint16_t	 lpi_portprio;
115 };
116 
117 struct lacp_port {
118 	struct lagg_port	*lp_laggport;
119 	bool			 lp_added_multi;
120 	int			 lp_timer[LACP_NTIMER];
121 	uint32_t		 lp_marker_xid;
122 	enum lacp_selected	 lp_selected;
123 	enum lacp_mux_state	 lp_mux_state;
124 
125 	struct lacp_portinfo	 lp_actor;
126 	struct lacp_portinfo	 lp_partner;
127 	struct lacp_aggregator	*lp_aggregator;
128 	struct lacp_aggregator_systemid
129 				 lp_aggregator_sidbuf;
130 	uint64_t		 lp_linkspeed;
131 	int			 lp_pending;
132 	LIST_ENTRY(lacp_port)	 lp_entry_la;
133 	struct timeval		 lp_last_lacpdu;
134 	int			 lp_lacpdu_sent;
135 	bool			 lp_collector;
136 
137 	unsigned int		 lp_flags;
138 #define LACP_PORT_NTT		__BIT(0)
139 #define LACP_PORT_MARK		__BIT(1)
140 
141 	struct lagg_work	 lp_work_smtx;
142 	struct lagg_work	 lp_work_marker;
143 };
144 
145 struct lacp_portmap {
146 	size_t			 pm_count;
147 	struct lagg_port	*pm_ports[LACP_MAX_PORTS];
148 };
149 
150 struct lacp_softc {
151 	struct lagg_softc	*lsc_softc;
152 	kmutex_t		 lsc_lock;
153 	pserialize_t		 lsc_psz;
154 	bool			 lsc_running;
155 	bool			 lsc_suppress_distributing;
156 	int			 lsc_timer[LACP_NPTIMER];
157 	uint8_t			 lsc_system_mac[LACP_MAC_LEN];
158 	uint16_t		 lsc_system_prio;
159 	uint16_t		 lsc_key;
160 	size_t			 lsc_max_ports;
161 	size_t			 lsc_activemap;
162 	struct lacp_portmap	 lsc_portmaps[2];	/* active & idle */
163 	struct lacp_aggregator	*lsc_aggregator;
164 	TAILQ_HEAD(, lacp_aggregator)
165 				 lsc_aggregators;
166 	struct workqueue	*lsc_workq;
167 	struct lagg_work	 lsc_work_tick;
168 	struct lagg_work	 lsc_work_rcvdu;
169 	struct lagg_work	 lsc_work_linkspeed;
170 	callout_t		 lsc_tick;
171 	pcq_t			*lsc_du_q;
172 
173 	char			 lsc_evgroup[32];
174 	struct evcnt		 lsc_mgethdr_failed;
175 	struct evcnt		 lsc_mpullup_failed;
176 	struct evcnt		 lsc_badlacpdu;
177 	struct evcnt		 lsc_badmarkerdu;
178 	struct evcnt		 lsc_norcvif;
179 	struct evcnt		 lsc_nolaggport;
180 	struct evcnt		 lsc_duq_nospc;
181 
182 	bool			 lsc_optimistic;
183 	bool			 lsc_stop_lacpdu;
184 	bool			 lsc_dump_du;
185 	bool			 lsc_multi_linkspeed;
186 };
187 
188 /*
189  * Locking notes:
190  * - Items in struct lacp_softc are protected by
191  *   lsc_lock (an adaptive mutex)
192  * - lsc_activemap is protected by pserialize (lsc_psz)
193  * - Items of struct lagg_port in lsc_portmaps are protected by
194  *   protected by both pserialize (lsc_psz) and psref (lp_psref)
195  * - Updates for lsc_activemap and lsc_portmaps is serialized by
196  *   sc_lock in struct lagg_softc
197  * - Other locking notes are described in if_laggproto.h
198  */
199 
200 static void	lacp_dprintf(const struct lacp_softc *,
201 		    const struct lacp_port *, const char *, ...)
202 		    __attribute__((__format__(__printf__, 3, 4)));
203 
204 #ifdef LACP_DEBUG
205 #define LACP_DPRINTF(a)	do { lacp_dprintf a; } while (/*CONSTCOND*/ 0)
206 #define LACP_PEERINFO_IDSTR(_pi, _b, _bs)			\
207 	lacp_peerinfo_idstr(_pi, _b, _bs)
208 #define LACP_STATE_STR(_s, _b, _bs)		lacp_state_str(_s, _b, _bs)
209 #define LACP_AGGREGATOR_STR(_a, _b, _bs)			\
210 	lacp_aggregator_str(_a, _b, _bs)
211 #define __LACPDEBUGUSED
212 #else
213 #define LACP_DPRINTF(a)				__nothing
214 #define LACP_PEERINFO_IDSTR(_pi, _b, _bs)	__nothing
215 #define LACP_STATE_STR(_s, _b, _bs)		__nothing
216 #define LACP_AGGREGATOR_STR(_a, _b, _bs)	__nothing
217 #define __LACPDEBUGUSED __unused
218 #endif
219 
220 #define LACP_LOCK(_sc)		mutex_enter(&(_sc)->lsc_lock)
221 #define LACP_UNLOCK(_sc)	mutex_exit(&(_sc)->lsc_lock)
222 #define LACP_LOCKED(_sc)	mutex_owned(&(_sc)->lsc_lock)
223 #define LACP_TIMER_ARM(_lacpp, _timer, _val)		\
224 	(_lacpp)->lp_timer[(_timer)] = (_val)
225 #define LACP_TIMER_DISARM(_lacpp, _timer)		\
226 	LACP_TIMER_ARM((_lacpp), (_timer), 0)
227 #define LACP_TIMER_ISARMED(_lacpp, _timer)		\
228 	((_lacpp)->lp_timer[(_timer)] > 0)
229 #define LACP_PTIMER_ARM(_sc, _timer, _val)		\
230 	(_sc)->lsc_timer[(_timer)] = (_val)
231 #define LACP_PTIMER_DISARM(_sc, _timer)			\
232 	LACP_PTIMER_ARM((_sc), (_timer), 0)
233 #define LACP_PTIMER_ISARMED(_sc, _timer)		\
234 	((_sc)->lsc_timer[(_timer)] > 0)
235 #define LACP_STATE_EQ(_s1, _s2, _mask)	(!ISSET((_s1) ^ (_s2), (_mask)))
236 #define LACP_PORT_XNAME(_lacpp)	(_lacpp != NULL) ?	\
237 	    (_lacpp)->lp_laggport->lp_ifp->if_xname : "(unknown)"
238 #define LACP_ISDUMPING(_sc)	(_sc)->lsc_dump_du
239 #define LACP_PORTMAP_ACTIVE(_sc)			\
240 	    atomic_load_consume(&(_sc)->lsc_activemap)
241 #define LACP_PORTMAP_NEXT(_sc)				\
242 	    (((LACP_PORTMAP_ACTIVE((_sc))) ^ 0x01) &0x01)
243 #define LACP_SYS_PRI(_la)	ntohs((_la)->la_sid.sid_prio)
244 #define LACP_TLV_PARSE(_du, _st, _name, _tlvlist)	\
245 	    tlv_parse(&(_du)->_name,			\
246 	    sizeof(_st) - offsetof(_st, _name),		\
247 	    (_tlvlist))
248 
249 static void	lacp_tick(void *);
250 static void	lacp_tick_work(struct lagg_work *, void *);
251 static void	lacp_linkstate(struct lagg_proto_softc *, struct lagg_port *);
252 static void	lacp_port_disable(struct lacp_softc *, struct lacp_port *);
253 static void	lacp_port_enable(struct lacp_softc *, struct lacp_port *);
254 static void	lacp_peerinfo_actor(struct lacp_softc *, struct lacp_port *,
255 		    struct lacpdu_peerinfo *);
256 static void	lacp_peerinfo_partner(struct lacp_port *,
257 		    struct lacpdu_peerinfo *);
258 static struct lagg_port *
259 		lacp_select_tx_port(struct lacp_softc *, struct mbuf *,
260 		    struct psref *);
261 static void	lacp_suppress_distributing(struct lacp_softc *);
262 static void	lacp_distributing_timer(struct lacp_softc *);
263 
264 static void	lacp_select(struct lacp_softc *, struct lacp_port *);
265 static void	lacp_unselect(struct lacp_softc *, struct lacp_port *);
266 static void	lacp_selected_update(struct lacp_softc *,
267 		    struct lacp_aggregator *);
268 static void	lacp_sm_port_init(struct lacp_softc *,
269 		    struct lacp_port *, struct lagg_port *);
270 static int	lacp_set_mux(struct lacp_softc *,
271 		    struct lacp_port *, enum lacp_mux_state);
272 static void	lacp_sm_mux(struct lacp_softc *, struct lacp_port *);
273 static void	lacp_sm_mux_timer(struct lacp_softc *, struct lacp_port *);
274 static void	lacp_sm_rx(struct lacp_softc *, struct lacp_port *,
275 		    struct lacpdu_peerinfo *, struct lacpdu_peerinfo *);
276 static void	lacp_sm_rx_set_expired(struct lacp_port *);
277 static void	lacp_sm_rx_timer(struct lacp_softc *, struct lacp_port *);
278 static void	lacp_sm_rx_record_default(struct lacp_softc *,
279 		    struct lacp_port *);
280 
281 static void	lacp_sm_tx(struct lacp_softc *, struct lacp_port *);
282 static void	lacp_sm_tx_work(struct lagg_work *, void *);
283 static void	lacp_sm_ptx_timer(struct lacp_softc *, struct lacp_port *);
284 static void	lacp_sm_ptx_schedule(struct lacp_port *);
285 static void	lacp_sm_ptx_update_timeout(struct lacp_port *, uint8_t);
286 
287 static void	lacp_rcvdu_work(struct lagg_work *, void *);
288 static void	lacp_marker_work(struct lagg_work *, void *);
289 static void	lacp_linkspeed_work(struct lagg_work *, void *);
290 static void	lacp_dump_lacpdutlv(const struct lacpdu_peerinfo *,
291 		    const struct lacpdu_peerinfo *,
292 		    const struct lacpdu_collectorinfo *);
293 static void	lacp_dump_markertlv(const struct markerdu_info *,
294 		    const struct markerdu_info *);
295 
296 typedef void (*lacp_timer_func_t)(struct lacp_softc *, struct lacp_port *);
297 static const lacp_timer_func_t	 lacp_timer_funcs[] = {
298 	[LACP_TIMER_CURRENT_WHILE] = lacp_sm_rx_timer,
299 	[LACP_TIMER_PERIODIC] = lacp_sm_ptx_timer,
300 	[LACP_TIMER_WAIT_WHILE] = lacp_sm_mux_timer,
301 };
302 typedef void (*lacp_prototimer_func_t)(struct lacp_softc *);
303 static const lacp_prototimer_func_t	 lacp_ptimer_funcs[] = {
304 	[LACP_PTIMER_DISTRIBUTING] = lacp_distributing_timer,
305 };
306 
307 static void
lacp_dprintf(const struct lacp_softc * lsc,const struct lacp_port * lacpp,const char * fmt,...)308 lacp_dprintf(const struct lacp_softc *lsc, const struct lacp_port *lacpp,
309     const char *fmt, ...)
310 {
311 	struct lagg_softc *sc;
312 	va_list va;
313 
314 	if (lsc != NULL && lsc->lsc_softc != NULL) {
315 		sc = lsc->lsc_softc;
316 		printf("%s", sc->sc_if.if_xname);
317 	} else {
318 		printf("lacp");
319 	}
320 
321 	if (lacpp != NULL)
322 		printf("(%s)", LACP_PORT_XNAME(lacpp));
323 
324 	printf(": ");
325 
326 	va_start(va, fmt);
327 	vprintf(fmt, va);
328 	va_end(va);
329 }
330 
331 static inline void
lacp_evcnt_attach(struct lacp_softc * lsc,struct evcnt * ev,const char * name)332 lacp_evcnt_attach(struct lacp_softc *lsc,
333     struct evcnt *ev, const char *name)
334 {
335 
336 	evcnt_attach_dynamic(ev, EVCNT_TYPE_MISC, NULL,
337 	    lsc->lsc_evgroup, name);
338 }
339 
340 static inline bool
lacp_iscollecting(struct lacp_port * lacpp)341 lacp_iscollecting(struct lacp_port *lacpp)
342 {
343 
344 	return atomic_load_relaxed(&lacpp->lp_collector);
345 }
346 
347 static inline bool
lacp_isdistributing(struct lacp_port * lacpp)348 lacp_isdistributing(struct lacp_port *lacpp)
349 {
350 
351 	return ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_DISTRIBUTING);
352 }
353 
354 static inline bool
lacp_isactive(struct lacp_softc * lsc,struct lacp_port * lacpp)355 lacp_isactive(struct lacp_softc *lsc, struct lacp_port *lacpp)
356 {
357 
358 	if (lacpp->lp_selected != LACP_SELECTED)
359 		return false;
360 
361 	if (lacpp->lp_aggregator == NULL)
362 		return false;
363 
364 	if (lacpp->lp_aggregator != lsc->lsc_aggregator)
365 		return false;
366 
367 	return true;
368 }
369 
370 static inline void
lacp_mcastaddr(struct ifreq * ifr,const char * if_xname)371 lacp_mcastaddr(struct ifreq *ifr, const char *if_xname)
372 {
373 	static const uint8_t addr[ETHER_ADDR_LEN] =
374 	    { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x02 };
375 
376 	memset(ifr, 0, sizeof(*ifr));
377 
378 	strlcpy(ifr->ifr_name, if_xname,
379 	    sizeof(ifr->ifr_name));
380 	ifr->ifr_addr.sa_len = sizeof(ifr->ifr_addr);
381 	ifr->ifr_addr.sa_family = AF_UNSPEC;
382 
383 	CTASSERT(sizeof(ifr->ifr_addr) >= sizeof(addr));
384 	memcpy(&ifr->ifr_addr.sa_data, addr, sizeof(addr));
385 }
386 
387 static inline u_int
lacp_portmap_linkstate(struct lacp_portmap * pm)388 lacp_portmap_linkstate(struct lacp_portmap *pm)
389 {
390 
391 	if (pm->pm_count == 0)
392 		return LINK_STATE_DOWN;
393 
394 	return LINK_STATE_UP;
395 }
396 
397 static inline struct lacp_port *
lacp_port_priority_max(struct lacp_port * a,struct lacp_port * b)398 lacp_port_priority_max(struct lacp_port *a, struct lacp_port *b)
399 {
400 	uint16_t pri_a, pri_b;
401 
402 	pri_a = ntohs(a->lp_actor.lpi_portprio);
403 	pri_b = ntohs(b->lp_actor.lpi_portprio);
404 
405 	if (pri_a < pri_b)
406 		return a;
407 	if (pri_b < pri_a)
408 		return b;
409 
410 	pri_a = ntohs(a->lp_partner.lpi_portprio);
411 	pri_b = ntohs(b->lp_partner.lpi_portprio);
412 
413 	if (pri_a < pri_b)
414 		return a;
415 	if (pri_b < pri_a)
416 		return b;
417 
418 	if (a->lp_linkspeed > b->lp_linkspeed)
419 		return a;
420 	if (b->lp_linkspeed > a->lp_linkspeed)
421 		return b;
422 
423 	return a;
424 }
425 
426 static void
tlv_parse(void * vp,size_t len,struct tlv * list)427 tlv_parse(void *vp, size_t len, struct tlv *list)
428 {
429 	struct tlvhdr *th;
430 	uint8_t *p;
431 	size_t l, i;
432 
433 	th = (struct tlvhdr *)vp;
434 	p = (uint8_t *)vp;
435 
436 	for (l = 0; l < len; l += th->tlv_length) {
437 		th = (struct tlvhdr *)(p + l);
438 
439 		if (th->tlv_type == TLV_TYPE_TERMINATE)
440 			break;
441 
442 		if (th->tlv_length <= 0)
443 			break;
444 
445 		for (i = 0; list[i].tlv_t != TLV_TYPE_TERMINATE; i++) {
446 			if (th->tlv_type != list[i].tlv_t)
447 				continue;
448 
449 			if (th->tlv_length - sizeof(*th) != list[i].tlv_l)
450 				break;
451 
452 			if (list[i].tlv_v == NULL) {
453 				list[i].tlv_v =
454 				    (void *)((uint8_t *)th + sizeof(*th));
455 			}
456 
457 			break;
458 		}
459 	}
460 }
461 
462 int
lacp_attach(struct lagg_softc * sc,struct lagg_proto_softc ** lscp)463 lacp_attach(struct lagg_softc *sc, struct lagg_proto_softc **lscp)
464 {
465 	struct lacp_softc *lsc;
466 	char xnamebuf[MAXCOMLEN];
467 	int error;
468 
469 	KASSERT(LAGG_LOCKED(sc));
470 
471 	lsc = kmem_zalloc(sizeof(*lsc), KM_NOSLEEP);
472 	if (lsc == NULL)
473 		return ENOMEM;
474 
475 	lsc->lsc_du_q = pcq_create(LACP_RCVDU_LIMIT, KM_NOSLEEP);
476 	if (lsc->lsc_du_q == NULL) {
477 		error = ENOMEM;
478 		goto free_lsc;
479 	}
480 
481 	mutex_init(&lsc->lsc_lock, MUTEX_DEFAULT, IPL_SOFTNET);
482 	lsc->lsc_softc = sc;
483 	lsc->lsc_key = htons(if_get_index(&sc->sc_if));
484 	lsc->lsc_system_prio = htons(LACP_SYSTEM_PRIO);
485 	lsc->lsc_running = false;
486 	lsc->lsc_max_ports = LACP_MAX_PORTS;
487 	lsc->lsc_multi_linkspeed = true;
488 	TAILQ_INIT(&lsc->lsc_aggregators);
489 
490 	lagg_work_set(&lsc->lsc_work_tick, lacp_tick_work, lsc);
491 	lagg_work_set(&lsc->lsc_work_rcvdu, lacp_rcvdu_work, lsc);
492 	lagg_work_set(&lsc->lsc_work_linkspeed,
493 	    lacp_linkspeed_work, lsc);
494 
495 	snprintf(xnamebuf, sizeof(xnamebuf), "%s.lacp",
496 	    sc->sc_if.if_xname);
497 	lsc->lsc_workq = lagg_workq_create(xnamebuf,
498 	    PRI_SOFTNET, IPL_SOFTNET, WQ_MPSAFE);
499 	if (lsc->lsc_workq == NULL) {
500 		LAGG_LOG(sc, LOG_ERR, "workqueue create failed\n");
501 		error = ENOMEM;
502 		goto destroy_lock;
503 	}
504 
505 	lsc->lsc_psz = pserialize_create();
506 
507 	callout_init(&lsc->lsc_tick, CALLOUT_MPSAFE);
508 	callout_setfunc(&lsc->lsc_tick, lacp_tick, lsc);
509 
510 	snprintf(lsc->lsc_evgroup, sizeof(lsc->lsc_evgroup),
511 	    "%s-lacp", sc->sc_if.if_xname);
512 	lacp_evcnt_attach(lsc, &lsc->lsc_mgethdr_failed, "MGETHDR failed");
513 	lacp_evcnt_attach(lsc, &lsc->lsc_mpullup_failed, "m_pullup failed");
514 	lacp_evcnt_attach(lsc, &lsc->lsc_badlacpdu, "Bad LACPDU received");
515 	lacp_evcnt_attach(lsc, &lsc->lsc_badmarkerdu, "Bad MarkerDU received");
516 	lacp_evcnt_attach(lsc, &lsc->lsc_norcvif, "No received interface");
517 	lacp_evcnt_attach(lsc, &lsc->lsc_nolaggport, "No lagg context");
518 	lacp_evcnt_attach(lsc, &lsc->lsc_duq_nospc, "No space left on queues");
519 
520 	if_link_state_change(&sc->sc_if, LINK_STATE_DOWN);
521 
522 	*lscp = (struct lagg_proto_softc *)lsc;
523 	return 0;
524 destroy_lock:
525 	mutex_destroy(&lsc->lsc_lock);
526 	pcq_destroy(lsc->lsc_du_q);
527 free_lsc:
528 	kmem_free(lsc, sizeof(*lsc));
529 
530 	return error;
531 }
532 
533 void
lacp_detach(struct lagg_proto_softc * xlsc)534 lacp_detach(struct lagg_proto_softc *xlsc)
535 {
536 	struct lacp_softc *lsc = (struct lacp_softc *)xlsc;
537 	struct lagg_softc *sc __diagused = lsc->lsc_softc;
538 
539 	KASSERT(TAILQ_EMPTY(&lsc->lsc_aggregators));
540 	KASSERT(SIMPLEQ_EMPTY(&sc->sc_ports));
541 
542 	LAGG_LOCK(lsc->lsc_softc);
543 	lacp_down(xlsc);
544 	LAGG_UNLOCK(lsc->lsc_softc);
545 
546 	lagg_workq_wait(lsc->lsc_workq, &lsc->lsc_work_rcvdu);
547 	lagg_workq_wait(lsc->lsc_workq, &lsc->lsc_work_tick);
548 	evcnt_detach(&lsc->lsc_mgethdr_failed);
549 	evcnt_detach(&lsc->lsc_mpullup_failed);
550 	evcnt_detach(&lsc->lsc_badlacpdu);
551 	evcnt_detach(&lsc->lsc_badmarkerdu);
552 	evcnt_detach(&lsc->lsc_norcvif);
553 	evcnt_detach(&lsc->lsc_nolaggport);
554 	evcnt_detach(&lsc->lsc_duq_nospc);
555 	lagg_workq_destroy(lsc->lsc_workq);
556 	pserialize_destroy(lsc->lsc_psz);
557 	mutex_destroy(&lsc->lsc_lock);
558 	pcq_destroy(lsc->lsc_du_q);
559 	kmem_free(lsc, sizeof(*lsc));
560 }
561 
562 int
lacp_up(struct lagg_proto_softc * xlsc)563 lacp_up(struct lagg_proto_softc *xlsc)
564 {
565 	struct lagg_softc *sc;
566 	struct lagg_port *lp;
567 	struct lacp_softc *lsc;
568 
569 	lsc = (struct lacp_softc *)xlsc;
570 	sc = lsc->lsc_softc;
571 
572 	KASSERT(LAGG_LOCKED(sc));
573 
574 	LACP_LOCK(lsc);
575 	if (memcmp(lsc->lsc_system_mac, LAGG_CLLADDR(sc),
576 	    sizeof(lsc->lsc_system_mac)) != 0) {
577 		memcpy(lsc->lsc_system_mac, LAGG_CLLADDR(sc),
578 		    sizeof(lsc->lsc_system_mac));
579 	}
580 	lsc->lsc_running = true;
581 	callout_schedule(&lsc->lsc_tick, hz);
582 	LACP_UNLOCK(lsc);
583 
584 	LAGG_PORTS_FOREACH(sc, lp) {
585 		lacp_linkstate(xlsc, lp);
586 	}
587 
588 	LACP_DPRINTF((lsc, NULL, "lacp start\n"));
589 
590 	return 0;
591 }
592 
593 static void
lacp_down_locked(struct lacp_softc * lsc)594 lacp_down_locked(struct lacp_softc *lsc)
595 {
596 	struct lagg_softc *sc;
597 	struct lagg_port *lp;
598 
599 	sc = lsc->lsc_softc;
600 
601 	KASSERT(LAGG_LOCKED(sc));
602 	KASSERT(LACP_LOCKED(lsc));
603 
604 	lsc->lsc_running = false;
605 	callout_halt(&lsc->lsc_tick, &lsc->lsc_lock);
606 
607 	LAGG_PORTS_FOREACH(sc, lp) {
608 		lacp_port_disable(lsc, lp->lp_proto_ctx);
609 	}
610 
611 	memset(lsc->lsc_system_mac, 0,
612 	    sizeof(lsc->lsc_system_mac));
613 
614 	LACP_DPRINTF((lsc, NULL, "lacp stopped\n"));
615 }
616 
617 void
lacp_down(struct lagg_proto_softc * xlsc)618 lacp_down(struct lagg_proto_softc *xlsc)
619 {
620 	struct lacp_softc *lsc;
621 
622 	lsc = (struct lacp_softc *)xlsc;
623 
624 	KASSERT(LAGG_LOCKED(lsc->lsc_softc));
625 
626 	LACP_LOCK(lsc);
627 	lacp_down_locked(lsc);
628 	LACP_UNLOCK(lsc);
629 }
630 
631 int
lacp_transmit(struct lagg_proto_softc * xlsc,struct mbuf * m)632 lacp_transmit(struct lagg_proto_softc *xlsc, struct mbuf *m)
633 {
634 	struct lacp_softc *lsc;
635 	struct lagg_port *lp;
636 	struct ifnet *ifp;
637 	struct psref psref;
638 
639 	lsc = (struct lacp_softc *)xlsc;
640 
641 	if (__predict_false(lsc->lsc_suppress_distributing)) {
642 		LACP_DPRINTF((lsc, NULL, "waiting transit\n"));
643 		m_freem(m);
644 		return EBUSY;
645 	}
646 
647 	lp = lacp_select_tx_port(lsc, m, &psref);
648 	if (__predict_false(lp == NULL)) {
649 		LACP_DPRINTF((lsc, NULL, "no distributing port\n"));
650 		ifp = &lsc->lsc_softc->sc_if;
651 		if_statinc(ifp, if_oerrors);
652 		m_freem(m);
653 		return ENOENT;
654 	}
655 
656 	lagg_output(lsc->lsc_softc, lp, m);
657 	lagg_port_putref(lp, &psref);
658 
659 	return 0;
660 }
661 
662 int
lacp_allocport(struct lagg_proto_softc * xlsc,struct lagg_port * lp)663 lacp_allocport(struct lagg_proto_softc *xlsc, struct lagg_port *lp)
664 {
665 	struct lagg_softc *sc;
666 	struct lacp_softc *lsc;
667 	struct lacp_port *lacpp;
668 	struct ifreq ifr;
669 	bool added_multi;
670 	int error;
671 
672 	lsc = (struct lacp_softc *)xlsc;
673 	sc = lsc->lsc_softc;
674 
675 	KASSERT(LAGG_LOCKED(sc));
676 	KASSERT(IFNET_LOCKED(lp->lp_ifp));
677 
678 	lacpp = kmem_zalloc(sizeof(*lacpp), KM_NOSLEEP);
679 	if (lacpp == NULL)
680 		return ENOMEM;
681 
682 	lacp_mcastaddr(&ifr, lp->lp_ifp->if_xname);
683 	error = lp->lp_ioctl(lp->lp_ifp, SIOCADDMULTI, (void *)&ifr);
684 
685 	switch (error) {
686 	case 0:
687 		added_multi = true;
688 		break;
689 	case EAFNOSUPPORT:
690 		added_multi = false;
691 		break;
692 	default:
693 		LAGG_LOG(sc, LOG_ERR, "SIOCADDMULTI failed on %s\n",
694 		    lp->lp_ifp->if_xname);
695 		kmem_free(lacpp, sizeof(*lacpp));
696 		return error;
697 	}
698 
699 	lacpp->lp_added_multi = added_multi;
700 	lagg_work_set(&lacpp->lp_work_smtx, lacp_sm_tx_work, lsc);
701 	lagg_work_set(&lacpp->lp_work_marker, lacp_marker_work, lsc);
702 
703 	LACP_LOCK(lsc);
704 	lacp_sm_port_init(lsc, lacpp, lp);
705 	LACP_UNLOCK(lsc);
706 
707 	lp->lp_proto_ctx = (void *)lacpp;
708 	lp->lp_prio = ntohs(lacpp->lp_actor.lpi_portprio);
709 
710 	return 0;
711 }
712 
713 void
lacp_startport(struct lagg_proto_softc * xlsc,struct lagg_port * lp)714 lacp_startport(struct lagg_proto_softc *xlsc, struct lagg_port *lp)
715 {
716 	struct lacp_port *lacpp;
717 	uint16_t prio;
718 
719 	lacpp = lp->lp_proto_ctx;
720 
721 	prio = (uint16_t)MIN(lp->lp_prio, UINT16_MAX);
722 	lacpp->lp_actor.lpi_portprio = htons(prio);
723 
724 	lacp_linkstate(xlsc, lp);
725 }
726 
727 void
lacp_stopport(struct lagg_proto_softc * xlsc,struct lagg_port * lp)728 lacp_stopport(struct lagg_proto_softc *xlsc, struct lagg_port *lp)
729 {
730 	struct lacp_softc *lsc;
731 	struct lacp_port *lacpp;
732 	int i;
733 
734 	lsc = (struct lacp_softc *)xlsc;
735 	lacpp = lp->lp_proto_ctx;
736 
737 	KASSERT(LAGG_LOCKED(lsc->lsc_softc));
738 
739 	LACP_LOCK(lsc);
740 	for (i = 0; i < LACP_NTIMER; i++) {
741 		LACP_TIMER_DISARM(lacpp, i);
742 	}
743 
744 	lacp_port_disable(lsc, lacpp);
745 	LACP_UNLOCK(lsc);
746 }
747 
748 void
lacp_freeport(struct lagg_proto_softc * xlsc,struct lagg_port * lp)749 lacp_freeport(struct lagg_proto_softc *xlsc, struct lagg_port *lp)
750 {
751 	struct lacp_softc *lsc;
752 	struct lacp_port *lacpp;
753 	struct ifreq ifr;
754 
755 	lsc = (struct lacp_softc *)xlsc;
756 	lacpp = lp->lp_proto_ctx;
757 
758 	KASSERT(LAGG_LOCKED(lsc->lsc_softc));
759 	KASSERT(IFNET_LOCKED(lp->lp_ifp));
760 
761 	lagg_workq_wait(lsc->lsc_workq, &lacpp->lp_work_smtx);
762 	lagg_workq_wait(lsc->lsc_workq, &lacpp->lp_work_marker);
763 
764 	if (lacpp->lp_added_multi) {
765 		lacp_mcastaddr(&ifr, LACP_PORT_XNAME(lacpp));
766 
767 		(void)lp->lp_ioctl(lp->lp_ifp, SIOCDELMULTI, (void *)&ifr);
768 	}
769 
770 	lp->lp_proto_ctx = NULL;
771 	kmem_free(lacpp, sizeof(*lacpp));
772 }
773 
774 void
lacp_protostat(struct lagg_proto_softc * xlsc,struct laggreqproto * resp)775 lacp_protostat(struct lagg_proto_softc *xlsc, struct laggreqproto *resp)
776 {
777 	struct laggreq_lacp *rplacp;
778 	struct lacp_softc *lsc;
779 	struct lacp_aggregator *la;
780 	struct lacp_aggregator_systemid *sid;
781 
782 	lsc = (struct lacp_softc *)xlsc;
783 
784 	LACP_LOCK(lsc);
785 	la = lsc->lsc_aggregator;
786 	rplacp = &resp->rp_lacp;
787 
788 	if (lsc->lsc_optimistic)
789 		SET(rplacp->flags, LAGGREQLACP_OPTIMISTIC);
790 	if (lsc->lsc_dump_du)
791 		SET(rplacp->flags, LAGGREQLACP_DUMPDU);
792 	if (lsc->lsc_stop_lacpdu)
793 		SET(rplacp->flags, LAGGREQLACP_STOPDU);
794 	if (lsc->lsc_multi_linkspeed)
795 		SET(rplacp->flags, LAGGREQLACP_MULTILS);
796 
797 	rplacp->maxports = lsc->lsc_max_ports;
798 	rplacp->actor_prio = ntohs(lsc->lsc_system_prio);
799 	memcpy(rplacp->actor_mac, lsc->lsc_system_mac,
800 	    sizeof(rplacp->actor_mac));
801 	rplacp->actor_key = ntohs(lsc->lsc_key);
802 
803 	if (la != NULL) {
804 		sid = &la->la_sid;
805 		rplacp->partner_prio = ntohs(sid->sid_prio);
806 		memcpy(rplacp->partner_mac, sid->sid_mac,
807 		    sizeof(rplacp->partner_mac));
808 		rplacp->partner_key = ntohs(sid->sid_key);
809 	}
810 	LACP_UNLOCK(lsc);
811 }
812 
813 void
lacp_portstat(struct lagg_proto_softc * xlsc,struct lagg_port * lp,struct laggreqport * resp)814 lacp_portstat(struct lagg_proto_softc *xlsc, struct lagg_port *lp,
815     struct laggreqport *resp)
816 {
817 	struct laggreq_lacpport *llp;
818 	struct lacp_softc *lsc;
819 	struct lacp_port *lacpp;
820 	struct lacp_aggregator *la;
821 	struct lacp_aggregator_systemid *sid;
822 
823 	lsc = (struct lacp_softc *)xlsc;
824 	lacpp = lp->lp_proto_ctx;
825 	la = lacpp->lp_aggregator;
826 	llp = &resp->rp_lacpport;
827 
828 	if (lacp_isactive(lsc, lacpp))
829 		SET(resp->rp_flags, LAGG_PORT_ACTIVE);
830 	if (lacp_iscollecting(lacpp))
831 		SET(resp->rp_flags, LAGG_PORT_COLLECTING);
832 	if (lacp_isdistributing(lacpp))
833 		SET(resp->rp_flags, LAGG_PORT_DISTRIBUTING);
834 	if (lacpp->lp_selected == LACP_STANDBY)
835 		SET(resp->rp_flags, LAGG_PORT_STANDBY);
836 
837 	if (la != NULL) {
838 		sid = &la->la_sid;
839 		llp->partner_prio = ntohs(sid->sid_prio);
840 		memcpy(llp->partner_mac, sid->sid_mac,
841 		    sizeof(llp->partner_mac));
842 		llp->partner_key = ntohs(sid->sid_key);
843 	}
844 
845 	llp->actor_portprio = ntohs(lacpp->lp_actor.lpi_portprio);
846 	llp->actor_portno = ntohs(lacpp->lp_actor.lpi_portno);
847 	llp->actor_state = lacpp->lp_actor.lpi_state;
848 
849 	llp->partner_portprio = ntohs(lacpp->lp_partner.lpi_portprio);
850 	llp->partner_portno = ntohs(lacpp->lp_partner.lpi_portno);
851 	llp->partner_state = lacpp->lp_partner.lpi_state;
852 }
853 
854 void
lacp_linkstate_ifnet_locked(struct lagg_proto_softc * xlsc,struct lagg_port * lp)855 lacp_linkstate_ifnet_locked(struct lagg_proto_softc *xlsc, struct lagg_port *lp)
856 {
857 	struct lacp_softc *lsc;
858 	struct lacp_port *lacpp;
859 	struct ifmediareq ifmr;
860 	struct ifnet *ifp_port;
861 	uint8_t old_state;
862 	uint64_t old_linkspeed, new_linkspeed;
863 	int error;
864 
865 	KASSERT(IFNET_LOCKED(lp->lp_ifp));
866 
867 	lsc = (struct lacp_softc *)xlsc;
868 
869 	ifp_port = lp->lp_ifp;
870 	lacpp = lp->lp_proto_ctx;
871 
872 	memset(&ifmr, 0, sizeof(ifmr));
873 	ifmr.ifm_count = 0;
874 	error = if_ioctl(ifp_port, SIOCGIFMEDIA, (void *)&ifmr);
875 	if (error == 0) {
876 		new_linkspeed = ifmedia_baudrate(ifmr.ifm_active);
877 #ifdef LACP_NOFDX
878 		/*
879 		 * some driver that has no media, e.g. vioif(4),
880 		 * returns (IFM_ETHER | IFM_AUTO)
881 		 */
882 		if ((ifmr.ifm_active & ~(IFM_ETHER | IFM_AUTO)) == 0)
883 			ifmr.ifm_active |= IFM_FDX;
884 #endif
885 	} else if (error == ENOTTY) {
886 		ifmr.ifm_active = IFM_FDX | IF_Gbps(0);
887 		new_linkspeed = 0;
888 	} else {
889 		LACP_DPRINTF((lsc, lacpp,
890 		    "SIOCGIFMEDIA failed (%d)\n", error));
891 		return;
892 	}
893 
894 	LACP_LOCK(lsc);
895 	if (lsc->lsc_running) {
896 		old_linkspeed = lacpp->lp_linkspeed;
897 		old_state = lacpp->lp_actor.lpi_state;
898 
899 		if (new_linkspeed != old_linkspeed) {
900 			LACP_DPRINTF((lsc, lacpp,
901 			    "linkspeed changed %"PRIu64" -> %"PRIu64"\n",
902 			    old_linkspeed, new_linkspeed));
903 			lacpp->lp_linkspeed = new_linkspeed;
904 		}
905 
906 		if (ISSET(ifmr.ifm_active, IFM_FDX) &&
907 		    ISSET(ifp_port->if_flags, IFF_RUNNING) &&
908 		    ifp_port->if_link_state != LINK_STATE_DOWN) {
909 			lacp_port_enable(lsc, lacpp);
910 		} else {
911 			LACP_DPRINTF((lsc, lacpp,
912 			    "FDX=%d, RUNNING=%d, link=%d\n",
913 			    ISSET(ifmr.ifm_active, IFM_FDX) != 0,
914 			    ISSET(ifp_port->if_flags, IFF_RUNNING) != 0,
915 			    ifp_port->if_link_state != LINK_STATE_DOWN));
916 			lacp_port_disable(lsc, lacpp);
917 		}
918 
919 		if (old_state != lacpp->lp_actor.lpi_state ||
920 		    old_linkspeed != new_linkspeed) {
921 			LACP_DPRINTF((lsc, lacpp,
922 			    "state changed to UNSELECTED\n"));
923 			lacpp->lp_selected = LACP_UNSELECTED;
924 		}
925 	} else {
926 		LACP_DPRINTF((lsc, lacpp,
927 		    "LACP is inactive, skip linkstate\n"));
928 	}
929 	LACP_UNLOCK(lsc);
930 }
931 
932 int
lacp_ioctl(struct lagg_proto_softc * xlsc,struct laggreqproto * lreq)933 lacp_ioctl(struct lagg_proto_softc *xlsc, struct laggreqproto *lreq)
934 {
935 	struct lacp_softc *lsc;
936 	struct laggreq_lacp *rplacp;
937 	struct lacp_aggregator *la;
938 	int error;
939 	size_t maxports;
940 	bool set;
941 
942 	lsc = (struct lacp_softc *)xlsc;
943 	rplacp = &lreq->rp_lacp;
944 	error = 0;
945 
946 	switch (rplacp->command) {
947 	case LAGGIOC_LACPSETFLAGS:
948 	case LAGGIOC_LACPCLRFLAGS:
949 		set = (rplacp->command == LAGGIOC_LACPSETFLAGS) ?
950 		    true : false;
951 
952 		LACP_LOCK(lsc);
953 
954 		if (ISSET(rplacp->flags, LAGGREQLACP_OPTIMISTIC))
955 			lsc->lsc_optimistic = set;
956 		if (ISSET(rplacp->flags, LAGGREQLACP_DUMPDU))
957 			lsc->lsc_dump_du = set;
958 		if (ISSET(rplacp->flags, LAGGREQLACP_STOPDU))
959 			lsc->lsc_stop_lacpdu = set;
960 
961 		if (ISSET(rplacp->flags, LAGGREQLACP_MULTILS) &&
962 		    lsc->lsc_multi_linkspeed != set) {
963 			lsc->lsc_multi_linkspeed = set;
964 			TAILQ_FOREACH(la, &lsc->lsc_aggregators, la_q) {
965 				lacp_selected_update(lsc, la);
966 			}
967 		}
968 
969 		LACP_UNLOCK(lsc);
970 		break;
971 	case LAGGIOC_LACPSETMAXPORTS:
972 	case LAGGIOC_LACPCLRMAXPORTS:
973 		maxports = (rplacp->command == LAGGIOC_LACPSETMAXPORTS) ?
974 		    rplacp->maxports : LACP_MAX_PORTS;
975 		if (0 == maxports || LACP_MAX_PORTS < maxports) {
976 			error = ERANGE;
977 			break;
978 		}
979 
980 		LACP_LOCK(lsc);
981 		if (lsc->lsc_max_ports != maxports) {
982 			lsc->lsc_max_ports = maxports;
983 			TAILQ_FOREACH(la, &lsc->lsc_aggregators, la_q) {
984 				lacp_selected_update(lsc, la);
985 			}
986 		}
987 		LACP_UNLOCK(lsc);
988 		break;
989 	default:
990 		error = ENOTTY;
991 	}
992 
993 	return error;
994 }
995 
996 static int
lacp_pdu_input(struct lacp_softc * lsc,struct lacp_port * lacpp,struct mbuf * m)997 lacp_pdu_input(struct lacp_softc *lsc, struct lacp_port *lacpp, struct mbuf *m)
998 {
999 	enum {
1000 		LACP_TLV_ACTOR = 0,
1001 		LACP_TLV_PARTNER,
1002 		LACP_TLV_COLLECTOR,
1003 		LACP_TLV_TERM,
1004 		LACP_TLV_NUM
1005 	};
1006 
1007 	struct lacpdu *du;
1008 	struct lacpdu_peerinfo *pi_actor, *pi_partner;
1009 	struct lacpdu_collectorinfo *lci;
1010 	struct tlv tlvlist_lacp[LACP_TLV_NUM] = {
1011 		[LACP_TLV_ACTOR] = {
1012 		    .tlv_t = LACP_TYPE_ACTORINFO,
1013 		    .tlv_l = sizeof(*pi_actor)},
1014 		[LACP_TLV_PARTNER] = {
1015 		    .tlv_t = LACP_TYPE_PARTNERINFO,
1016 		    .tlv_l = sizeof(*pi_partner)},
1017 		[LACP_TLV_COLLECTOR] = {
1018 		    .tlv_t = LACP_TYPE_COLLECTORINFO,
1019 		    .tlv_l = sizeof(*lci)},
1020 		[LACP_TLV_TERM] = {
1021 		    .tlv_t = TLV_TYPE_TERMINATE,
1022 		    .tlv_l = 0},
1023 	};
1024 
1025 	if (m->m_pkthdr.len != sizeof(*du))
1026 		goto bad;
1027 
1028 	if (m->m_len < (int)sizeof(*du)) {
1029 		m = m_pullup(m, sizeof(*du));
1030 		if (m == NULL) {
1031 			lsc->lsc_mpullup_failed.ev_count++;
1032 			return ENOMEM;
1033 		}
1034 	}
1035 
1036 	du = mtod(m, struct lacpdu *);
1037 
1038 	if (memcmp(&du->ldu_eh.ether_dhost,
1039 	    ethermulticastaddr_slowprotocols, ETHER_ADDR_LEN) != 0)
1040 		goto bad;
1041 
1042 	LACP_TLV_PARSE(du, struct lacpdu, ldu_tlv_actor,
1043 	    tlvlist_lacp);
1044 
1045 	pi_actor = tlvlist_lacp[LACP_TLV_ACTOR].tlv_v;
1046 	pi_partner = tlvlist_lacp[LACP_TLV_PARTNER].tlv_v;
1047 	lci = tlvlist_lacp[LACP_TLV_COLLECTOR].tlv_v;
1048 
1049 	if (pi_actor == NULL || pi_partner == NULL)
1050 		goto bad;
1051 
1052 	if (LACP_ISDUMPING(lsc)) {
1053 		lacp_dprintf(lsc, lacpp, "lacpdu received\n");
1054 		lacp_dump_lacpdutlv(pi_actor, pi_partner, lci);
1055 	}
1056 
1057 	LACP_LOCK(lsc);
1058 	lacp_sm_rx(lsc, lacpp, pi_partner, pi_actor);
1059 	LACP_UNLOCK(lsc);
1060 
1061 	m_freem(m);
1062 	return 0;
1063 bad:
1064 	lsc->lsc_badlacpdu.ev_count++;
1065 	m_freem(m);
1066 	return EINVAL;
1067 }
1068 
1069 static int
marker_cmp(struct markerdu_info * mi,struct lacp_softc * lsc,struct lacp_port * lacpp)1070 marker_cmp(struct markerdu_info *mi,
1071     struct lacp_softc *lsc, struct lacp_port *lacpp)
1072 {
1073 
1074 	KASSERT(LACP_LOCKED(lsc));
1075 
1076 	if (mi->mi_rq_port != lacpp->lp_actor.lpi_portno)
1077 		return -1;
1078 
1079 	if (ntohl(mi->mi_rq_xid) != lacpp->lp_marker_xid)
1080 		return -1;
1081 
1082 	return  memcmp(mi->mi_rq_system, lsc->lsc_system_mac,
1083 	    LACP_MAC_LEN);
1084 }
1085 
1086 static void
lacp_marker_reply(struct lacp_softc * lsc,struct lacp_port * lacpp,struct mbuf * m_info)1087 lacp_marker_reply(struct lacp_softc *lsc, struct lacp_port *lacpp,
1088     struct mbuf *m_info)
1089 {
1090 	struct lagg_port *lp;
1091 	struct markerdu *mdu;
1092 	struct ifnet *ifp_port;
1093 	struct psref psref;
1094 
1095 	LACP_LOCK(lsc);
1096 	lp = lacpp->lp_laggport;
1097 	lagg_port_getref(lp, &psref);
1098 	LACP_UNLOCK(lsc);
1099 
1100 	ifp_port = lp->lp_ifp;
1101 	mdu = mtod(m_info, struct markerdu *);
1102 
1103 	mdu->mdu_tlv_info.tlv_type = MARKER_TYPE_RESPONSE;
1104 	/* ether_dhost is already ethermulticastaddr_slowprotocols */
1105 	m_info->m_flags |= M_MCAST;
1106 	memcpy(mdu->mdu_eh.ether_shost,
1107 	    CLLADDR(ifp_port->if_sadl), ETHER_ADDR_LEN);
1108 
1109 	if (LACP_ISDUMPING(lsc)) {
1110 		lacp_dprintf(lsc, lacpp, "markerdu reply\n");
1111 		lacp_dump_markertlv(NULL, &mdu->mdu_info);
1112 	}
1113 
1114 	lagg_port_xmit(lp, m_info);
1115 	lagg_port_putref(lp, &psref);
1116 }
1117 
1118 static int
lacp_marker_recv_response(struct lacp_softc * lsc,struct lacp_port * lacpp,struct markerdu_info * mi_res)1119 lacp_marker_recv_response(struct lacp_softc *lsc, struct lacp_port *lacpp,
1120     struct markerdu_info *mi_res)
1121 {
1122 	struct lagg_softc *sc;
1123 	struct lagg_port *lp0;
1124 	struct lacp_port *lacpp0;
1125 	bool pending;
1126 
1127 	sc = lsc->lsc_softc;
1128 
1129 	LACP_LOCK(lsc);
1130 	if (marker_cmp(mi_res, lsc, lacpp) != 0) {
1131 		LACP_UNLOCK(lsc);
1132 		return -1;
1133 	}
1134 	CLR(lacpp->lp_flags, LACP_PORT_MARK);
1135 	LACP_UNLOCK(lsc);
1136 
1137 	LAGG_LOCK(sc);
1138 	LACP_LOCK(lsc);
1139 
1140 	if (lsc->lsc_suppress_distributing) {
1141 		pending = false;
1142 		LAGG_PORTS_FOREACH(sc, lp0) {
1143 			lacpp0 = lp0->lp_proto_ctx;
1144 			if (ISSET(lacpp0->lp_flags, LACP_PORT_MARK)) {
1145 				pending = true;
1146 				break;
1147 			}
1148 		}
1149 
1150 		if (!pending) {
1151 			LACP_DPRINTF((lsc, NULL, "queue flush complete\n"));
1152 			LACP_PTIMER_DISARM(lsc, LACP_PTIMER_DISTRIBUTING);
1153 			lsc->lsc_suppress_distributing = false;
1154 		}
1155 	}
1156 
1157 	LACP_UNLOCK(lsc);
1158 	LAGG_UNLOCK(sc);
1159 
1160 	return 0;
1161 }
1162 
1163 static int
lacp_marker_input(struct lacp_softc * lsc,struct lacp_port * lacpp,struct mbuf * m)1164 lacp_marker_input(struct lacp_softc *lsc, struct lacp_port *lacpp,
1165     struct mbuf *m)
1166 {
1167 	enum {
1168 		MARKER_TLV_INFO = 0,
1169 		MARKER_TLV_RESPONSE,
1170 		MARKER_TLV_TERM,
1171 		MARKER_TLV_NUM
1172 	};
1173 
1174 	struct markerdu *mdu;
1175 	struct markerdu_info *mi_info, *mi_res;
1176 	int error;
1177 	struct tlv tlvlist_marker[MARKER_TLV_NUM] = {
1178 		[MARKER_TLV_INFO] = {
1179 		    .tlv_t = MARKER_TYPE_INFO,
1180 		    .tlv_l = sizeof(*mi_info)},
1181 		[MARKER_TLV_RESPONSE] = {
1182 		    .tlv_t = MARKER_TYPE_RESPONSE,
1183 		    .tlv_l = sizeof(*mi_res)},
1184 		[MARKER_TLV_TERM] = {
1185 		    .tlv_t = TLV_TYPE_TERMINATE,
1186 		    .tlv_l = 0},
1187 	};
1188 
1189 	if (m->m_pkthdr.len != sizeof(*mdu))
1190 		goto bad;
1191 
1192 	if (m->m_len < (int)sizeof(*mdu)) {
1193 		m = m_pullup(m, sizeof(*mdu));
1194 		if (m == NULL) {
1195 			lsc->lsc_mpullup_failed.ev_count++;
1196 			return ENOMEM;
1197 		}
1198 	}
1199 
1200 	mdu = mtod(m, struct markerdu *);
1201 
1202 	if (memcmp(mdu->mdu_eh.ether_dhost,
1203 	    ethermulticastaddr_slowprotocols, ETHER_ADDR_LEN) != 0)
1204 		goto bad;
1205 
1206 	LACP_TLV_PARSE(mdu, struct markerdu, mdu_tlv_info,
1207 	    tlvlist_marker);
1208 
1209 	mi_info = tlvlist_marker[MARKER_TLV_INFO].tlv_v;
1210 	mi_res = tlvlist_marker[MARKER_TLV_RESPONSE].tlv_v;
1211 
1212 	if (LACP_ISDUMPING(lsc)) {
1213 		lacp_dprintf(lsc, lacpp, "markerdu received\n");
1214 		lacp_dump_markertlv(mi_info, mi_res);
1215 	}
1216 
1217 	if (mi_info != NULL && mi_res == NULL) {
1218 		lacp_marker_reply(lsc, lacpp, m);
1219 	} else if (mi_info == NULL && mi_res != NULL) {
1220 		error = lacp_marker_recv_response(lsc, lacpp,
1221 		    mi_res);
1222 		if (error != 0) {
1223 			goto bad;
1224 		} else {
1225 			m_freem(m);
1226 		}
1227 	} else {
1228 		goto bad;
1229 	}
1230 
1231 	return 0;
1232 bad:
1233 	lsc->lsc_badmarkerdu.ev_count++;
1234 	m_freem(m);
1235 	return EINVAL;
1236 }
1237 
1238 struct mbuf *
lacp_input(struct lagg_proto_softc * xlsc,struct lagg_port * lp,struct mbuf * m)1239 lacp_input(struct lagg_proto_softc *xlsc, struct lagg_port *lp, struct mbuf *m)
1240 {
1241 	struct ifnet *ifp;
1242 	struct lacp_softc *lsc;
1243 	struct lacp_port *lacpp;
1244 	struct ether_header *eh;
1245 	uint8_t subtype;
1246 
1247 	eh = mtod(m, struct ether_header *);
1248 	lsc = (struct lacp_softc *)xlsc;
1249 	ifp = &lsc->lsc_softc->sc_if;
1250 	lacpp = lp->lp_proto_ctx;
1251 
1252 	if (!vlan_has_tag(m) &&
1253 	    eh->ether_type == htons(ETHERTYPE_SLOWPROTOCOLS)) {
1254 		if (m->m_pkthdr.len < (int)(sizeof(*eh) + sizeof(subtype))) {
1255 			m_freem(m);
1256 			return NULL;
1257 		}
1258 
1259 		m_copydata(m, sizeof(struct ether_header),
1260 		    sizeof(subtype), &subtype);
1261 
1262 		switch (subtype) {
1263 		case SLOWPROTOCOLS_SUBTYPE_LACP:
1264 		case SLOWPROTOCOLS_SUBTYPE_MARKER:
1265 			if (pcq_put(lsc->lsc_du_q, (void *)m)) {
1266 				lagg_workq_add(lsc->lsc_workq,
1267 				    &lsc->lsc_work_rcvdu);
1268 			} else {
1269 				m_freem(m);
1270 				lsc->lsc_duq_nospc.ev_count++;
1271 			}
1272 			return NULL;
1273 		}
1274 	}
1275 
1276 	if (!lacp_iscollecting(lacpp) || !lacp_isactive(lsc, lacpp)) {
1277 		if_statinc(ifp, if_ierrors);
1278 		m_freem(m);
1279 		return NULL;
1280 	}
1281 
1282 	return m;
1283 }
1284 
1285 static void
lacp_rcvdu_work(struct lagg_work * lw __unused,void * xlsc)1286 lacp_rcvdu_work(struct lagg_work *lw __unused, void *xlsc)
1287 {
1288 	struct lacp_softc *lsc = (struct lacp_softc *)xlsc;
1289 	struct ifnet *ifp;
1290 	struct psref psref_lp;
1291 	struct lagg_port *lp;
1292 	struct mbuf *m;
1293 	uint8_t subtype;
1294 	int bound, s0, s1;
1295 
1296 	bound = curlwp_bind();
1297 
1298 	for (;;) {
1299 		m = pcq_get(lsc->lsc_du_q);
1300 		if (m == NULL)
1301 			break;
1302 
1303 		ifp = m_get_rcvif(m, &s0);
1304 		if (ifp == NULL) {
1305 			m_freem(m);
1306 			lsc->lsc_norcvif.ev_count++;
1307 			continue;
1308 		}
1309 
1310 		s1 = pserialize_read_enter();
1311 		lp = atomic_load_consume(&ifp->if_lagg);
1312 		if (lp == NULL) {
1313 			pserialize_read_exit(s1);
1314 			m_put_rcvif(ifp, &s0);
1315 			m_freem(m);
1316 			lsc->lsc_norcvif.ev_count++;
1317 			continue;
1318 		}
1319 
1320 		lagg_port_getref(lp, &psref_lp);
1321 		pserialize_read_exit(s1);
1322 		m_put_rcvif(ifp, &s0);
1323 
1324 		m_copydata(m, sizeof(struct ether_header),
1325 		    sizeof(subtype), &subtype);
1326 
1327 		switch (subtype) {
1328 		case SLOWPROTOCOLS_SUBTYPE_LACP:
1329 			(void)lacp_pdu_input(lsc,
1330 			    lp->lp_proto_ctx, m);
1331 			break;
1332 		case SLOWPROTOCOLS_SUBTYPE_MARKER:
1333 			(void)lacp_marker_input(lsc,
1334 			    lp->lp_proto_ctx, m);
1335 			break;
1336 		}
1337 
1338 		lagg_port_putref(lp, &psref_lp);
1339 	}
1340 
1341 	curlwp_bindx(bound);
1342 }
1343 
1344 static bool
lacp_port_need_to_tell(struct lacp_port * lacpp)1345 lacp_port_need_to_tell(struct lacp_port *lacpp)
1346 {
1347 
1348 	if (!ISSET(lacpp->lp_actor.lpi_state,
1349 	    LACP_STATE_AGGREGATION)) {
1350 		return false;
1351 	}
1352 
1353 	if (!ISSET(lacpp->lp_actor.lpi_state,
1354 	    LACP_STATE_ACTIVITY)
1355 	    && !ISSET(lacpp->lp_partner.lpi_state,
1356 	    LACP_STATE_ACTIVITY)) {
1357 		return false;
1358 	}
1359 
1360 	if (!ISSET(lacpp->lp_flags, LACP_PORT_NTT))
1361 		return false;
1362 
1363 	return true;
1364 }
1365 
1366 static void
lacp_sm_assert_ntt(struct lacp_port * lacpp)1367 lacp_sm_assert_ntt(struct lacp_port *lacpp)
1368 {
1369 
1370 	SET(lacpp->lp_flags, LACP_PORT_NTT);
1371 }
1372 
1373 static void
lacp_sm_negate_ntt(struct lacp_port * lacpp)1374 lacp_sm_negate_ntt(struct lacp_port *lacpp)
1375 {
1376 
1377 	CLR(lacpp->lp_flags, LACP_PORT_NTT);
1378 }
1379 
1380 static struct mbuf *
lacp_lacpdu_mbuf(struct lacp_softc * lsc,struct lacp_port * lacpp)1381 lacp_lacpdu_mbuf(struct lacp_softc *lsc, struct lacp_port *lacpp)
1382 {
1383 	struct ifnet *ifp_port;
1384 	struct mbuf *m;
1385 	struct lacpdu *du;
1386 
1387 	KASSERT(LACP_LOCKED(lsc));
1388 
1389 	ifp_port = lacpp->lp_laggport->lp_ifp;
1390 
1391 	MGETHDR(m, M_DONTWAIT, MT_DATA);
1392 	if (m == NULL) {
1393 		lsc->lsc_mgethdr_failed.ev_count++;
1394 		return NULL;
1395 	}
1396 
1397 	m->m_pkthdr.len = m->m_len = sizeof(*du);
1398 	m_reset_rcvif(m);
1399 
1400 	du = mtod(m, struct lacpdu *);
1401 	memset(du, 0, sizeof(*du));
1402 
1403 	m->m_flags |= M_MCAST;
1404 	memcpy(du->ldu_eh.ether_dhost, ethermulticastaddr_slowprotocols,
1405 	    ETHER_ADDR_LEN);
1406 	memcpy(du->ldu_eh.ether_shost, CLLADDR(ifp_port->if_sadl),
1407 	    ETHER_ADDR_LEN);
1408 	du->ldu_eh.ether_type = htons(ETHERTYPE_SLOWPROTOCOLS);
1409 	du->ldu_sph.sph_subtype = SLOWPROTOCOLS_SUBTYPE_LACP;
1410 	du->ldu_sph.sph_version = 1;
1411 
1412 	tlv_set(&du->ldu_tlv_actor, LACP_TYPE_ACTORINFO,
1413 	    sizeof(du->ldu_actor));
1414 	lacp_peerinfo_actor(lsc, lacpp, &du->ldu_actor);
1415 
1416 	tlv_set(&du->ldu_tlv_partner, LACP_TYPE_PARTNERINFO,
1417 	    sizeof(du->ldu_partner));
1418 	lacp_peerinfo_partner(lacpp, &du->ldu_partner);
1419 
1420 	tlv_set(&du->ldu_tlv_collector, LACP_TYPE_COLLECTORINFO,
1421 	    sizeof(du->ldu_collector));
1422 	du->ldu_collector.lci_maxdelay = 0;
1423 
1424 	du->ldu_tlv_term.tlv_type = LACP_TYPE_TERMINATE;
1425 	du->ldu_tlv_term.tlv_length = 0;
1426 
1427 	return m;
1428 }
1429 
1430 static void
lacp_sm_tx_work(struct lagg_work * lw,void * xlsc)1431 lacp_sm_tx_work(struct lagg_work *lw, void *xlsc)
1432 {
1433 	struct lacp_softc *lsc;
1434 	struct lacp_port *lacpp;
1435 	struct lagg_port *lp;
1436 	struct lacpdu *du;
1437 	struct mbuf *m;
1438 	struct psref psref;
1439 	int bound;
1440 
1441 	lsc = xlsc;
1442 	lacpp = container_of(lw, struct lacp_port, lp_work_smtx);
1443 
1444 	LACP_LOCK(lsc);
1445 
1446 	if (lsc->lsc_stop_lacpdu) {
1447 		LACP_UNLOCK(lsc);
1448 		return;
1449 	}
1450 
1451 	m = lacp_lacpdu_mbuf(lsc, lacpp);
1452 	if (m == NULL) {
1453 		LACP_UNLOCK(lsc);
1454 		return;
1455 	}
1456 	lacp_sm_negate_ntt(lacpp);
1457 	lp = lacpp->lp_laggport;
1458 	bound = curlwp_bind();
1459 	lagg_port_getref(lp, &psref);
1460 	LACP_UNLOCK(lsc);
1461 
1462 	if (LACP_ISDUMPING(lsc)) {
1463 		lacp_dprintf(lsc, lacpp, "lacpdu transmit\n");
1464 		du = mtod(m, struct lacpdu *);
1465 		lacp_dump_lacpdutlv(&du->ldu_actor,
1466 		    &du->ldu_partner, &du->ldu_collector);
1467 	}
1468 
1469 	lagg_port_xmit(lp, m);
1470 	lagg_port_putref(lp, &psref);
1471 	curlwp_bindx(bound);
1472 }
1473 
1474 static void
lacp_sm_tx(struct lacp_softc * lsc,struct lacp_port * lacpp)1475 lacp_sm_tx(struct lacp_softc *lsc, struct lacp_port *lacpp)
1476 {
1477 
1478 	if (!lacp_port_need_to_tell(lacpp))
1479 		return;
1480 
1481 	lagg_workq_add(lsc->lsc_workq, &lacpp->lp_work_smtx);
1482 }
1483 
1484 static void
lacp_tick(void * xlsc)1485 lacp_tick(void *xlsc)
1486 {
1487 	struct lacp_softc *lsc;
1488 
1489 	lsc = xlsc;
1490 
1491 	LACP_LOCK(lsc);
1492 
1493 	if (!lsc->lsc_running) {
1494 		LACP_UNLOCK(lsc);
1495 		return;
1496 	}
1497 
1498 	lagg_workq_add(lsc->lsc_workq, &lsc->lsc_work_tick);
1499 	callout_schedule(&lsc->lsc_tick, hz);
1500 
1501 	LACP_UNLOCK(lsc);
1502 }
1503 
1504 static void
lacp_run_timers(struct lacp_softc * lsc,struct lacp_port * lacpp)1505 lacp_run_timers(struct lacp_softc *lsc, struct lacp_port *lacpp)
1506 {
1507 	size_t i;
1508 
1509 	KASSERT(LACP_LOCKED(lsc));
1510 
1511 	for (i = 0; i < LACP_NTIMER; i++) {
1512 		KASSERT(lacpp->lp_timer[i] >= 0);
1513 
1514 		if (lacpp->lp_timer[i] == 0)
1515 			continue;
1516 		if (--lacpp->lp_timer[i] > 0)
1517 			continue;
1518 
1519 		KASSERT(lacp_timer_funcs[i] != NULL);
1520 		lacp_timer_funcs[i](lsc, lacpp);
1521 	}
1522 }
1523 
1524 static void
lacp_run_prototimers(struct lacp_softc * lsc)1525 lacp_run_prototimers(struct lacp_softc *lsc)
1526 {
1527 	size_t i;
1528 
1529 	for (i = 0; i < LACP_NPTIMER; i++) {
1530 		KASSERT(lsc->lsc_timer[i] >= 0);
1531 
1532 		if (lsc->lsc_timer[i] == 0)
1533 			continue;
1534 		if (--lsc->lsc_timer[i] > 0)
1535 			continue;
1536 
1537 		KASSERT(lacp_ptimer_funcs[i] != NULL);
1538 		lacp_ptimer_funcs[i](lsc);
1539 	}
1540 }
1541 
1542 static void
lacp_tick_work(struct lagg_work * lw __unused,void * xlsc)1543 lacp_tick_work(struct lagg_work *lw __unused, void *xlsc)
1544 {
1545 	struct lacp_softc *lsc;
1546 	struct lacp_port *lacpp;
1547 	struct lagg_softc *sc;
1548 	struct lagg_port *lp;
1549 
1550 	lsc = xlsc;
1551 	sc = lsc->lsc_softc;
1552 
1553 	LACP_LOCK(lsc);
1554 	if (!lsc->lsc_running) {
1555 		LACP_UNLOCK(lsc);
1556 		return;
1557 	}
1558 
1559 	lacp_run_prototimers(lsc);
1560 	LACP_UNLOCK(lsc);
1561 
1562 	LAGG_LOCK(sc);
1563 	LACP_LOCK(lsc);
1564 	LAGG_PORTS_FOREACH(sc, lp) {
1565 		lacpp = lp->lp_proto_ctx;
1566 		if (!ISSET(lacpp->lp_actor.lpi_state,
1567 		    LACP_STATE_AGGREGATION)) {
1568 			continue;
1569 		}
1570 
1571 		lacp_run_timers(lsc, lacpp);
1572 		lacp_select(lsc, lacpp);
1573 		lacp_sm_mux(lsc, lacpp);
1574 		lacp_sm_tx(lsc, lacpp);
1575 		lacp_sm_ptx_schedule(lacpp);
1576 	}
1577 
1578 	LACP_UNLOCK(lsc);
1579 	LAGG_UNLOCK(sc);
1580 }
1581 
1582 static void
lacp_systemid_str(char * buf,size_t buflen,uint16_t prio,const uint8_t * mac,uint16_t key)1583 lacp_systemid_str(char *buf, size_t buflen,
1584     uint16_t prio, const uint8_t *mac, uint16_t key)
1585 {
1586 
1587 	snprintf(buf, buflen,
1588 	    "%04X,"
1589 	    "%02X-%02X-%02X-%02X-%02X-%02X,"
1590 	    "%04X",
1591 	    (unsigned int)ntohs(prio),
1592 	    (int)mac[0], (int)mac[1], (int)mac[2],
1593 	    (int)mac[3], (int)mac[4], (int)mac[5],
1594 	    (unsigned int)htons(key));
1595 
1596 }
1597 
1598 __LACPDEBUGUSED static void
lacp_aggregator_str(struct lacp_aggregator * la,char * buf,size_t buflen)1599 lacp_aggregator_str(struct lacp_aggregator *la, char *buf, size_t buflen)
1600 {
1601 
1602 	lacp_systemid_str(buf, buflen, la->la_sid.sid_prio,
1603 	    la->la_sid.sid_mac, la->la_sid.sid_key);
1604 }
1605 
1606 static void
lacp_peerinfo_idstr(const struct lacpdu_peerinfo * pi,char * buf,size_t buflen)1607 lacp_peerinfo_idstr(const struct lacpdu_peerinfo *pi,
1608     char *buf, size_t buflen)
1609 {
1610 
1611 	lacp_systemid_str(buf, buflen, pi->lpi_system_prio,
1612 	    pi->lpi_system_mac, pi->lpi_key);
1613 }
1614 
1615 static void
lacp_state_str(uint8_t state,char * buf,size_t buflen)1616 lacp_state_str(uint8_t state, char *buf, size_t buflen)
1617 {
1618 
1619 	snprintb(buf, buflen, LACP_STATE_BITS, state);
1620 }
1621 
1622 static struct lagg_port *
lacp_select_tx_port(struct lacp_softc * lsc,struct mbuf * m,struct psref * psref)1623 lacp_select_tx_port(struct lacp_softc *lsc, struct mbuf *m,
1624     struct psref *psref)
1625 {
1626 	struct lacp_portmap *pm;
1627 	struct lagg_port *lp;
1628 	uint32_t hash;
1629 	size_t act;
1630 	int s;
1631 
1632 	hash = lagg_hashmbuf(lsc->lsc_softc, m);
1633 
1634 	s = pserialize_read_enter();
1635 	act = LACP_PORTMAP_ACTIVE(lsc);
1636 	pm = &lsc->lsc_portmaps[act];
1637 
1638 	if (pm->pm_count == 0) {
1639 		pserialize_read_exit(s);
1640 		return NULL;
1641 	}
1642 
1643 	hash %= pm->pm_count;
1644 	lp = pm->pm_ports[hash];
1645 	lagg_port_getref(lp, psref);
1646 
1647 	pserialize_read_exit(s);
1648 
1649 	return lp;
1650 }
1651 
1652 static void
lacp_peerinfo_actor(struct lacp_softc * lsc,struct lacp_port * lacpp,struct lacpdu_peerinfo * dst)1653 lacp_peerinfo_actor(struct lacp_softc *lsc, struct lacp_port *lacpp,
1654     struct lacpdu_peerinfo *dst)
1655 {
1656 
1657 	memcpy(dst->lpi_system_mac, lsc->lsc_system_mac, LACP_MAC_LEN);
1658 	dst->lpi_system_prio = lsc->lsc_system_prio;
1659 	dst->lpi_key = lsc->lsc_key;
1660 	dst->lpi_port_no = lacpp->lp_actor.lpi_portno;
1661 	dst->lpi_port_prio = lacpp->lp_actor.lpi_portprio;
1662 	dst->lpi_state = lacpp->lp_actor.lpi_state;
1663 }
1664 
1665 static void
lacp_peerinfo_partner(struct lacp_port * lacpp,struct lacpdu_peerinfo * dst)1666 lacp_peerinfo_partner(struct lacp_port *lacpp, struct lacpdu_peerinfo *dst)
1667 {
1668 	struct lacp_aggregator *la;
1669 
1670 	la = lacpp->lp_aggregator;
1671 
1672 	if (la != NULL) {
1673 		memcpy(dst->lpi_system_mac, la->la_sid.sid_mac, LACP_MAC_LEN);
1674 		dst->lpi_system_prio = la->la_sid.sid_prio;
1675 		dst->lpi_key = la->la_sid.sid_key;
1676 	} else {
1677 		memset(dst->lpi_system_mac, 0, LACP_MAC_LEN);
1678 		dst->lpi_system_prio = 0;
1679 		dst->lpi_key = 0;
1680 	}
1681 	dst->lpi_port_no = lacpp->lp_partner.lpi_portno;
1682 	dst->lpi_port_prio = lacpp->lp_partner.lpi_portprio;
1683 	dst->lpi_state = lacpp->lp_partner.lpi_state;
1684 }
1685 
1686 static int
lacp_compare_peerinfo(struct lacpdu_peerinfo * a,struct lacpdu_peerinfo * b)1687 lacp_compare_peerinfo(struct lacpdu_peerinfo *a, struct lacpdu_peerinfo *b)
1688 {
1689 
1690 	return memcmp(a, b, offsetof(struct lacpdu_peerinfo, lpi_state));
1691 }
1692 
1693 static void
lacp_sm_rx_record_default(struct lacp_softc * lsc,struct lacp_port * lacpp)1694 lacp_sm_rx_record_default(struct lacp_softc *lsc, struct lacp_port *lacpp)
1695 {
1696 	uint8_t oldpstate;
1697 	struct lacp_portinfo *pi;
1698 	char buf[LACP_STATESTR_LEN] __LACPDEBUGUSED;
1699 
1700 	pi = &lacpp->lp_partner;
1701 
1702 	oldpstate = pi->lpi_state;
1703 	pi->lpi_portno = htons(LACP_PORTNO_NONE);
1704 	pi->lpi_portprio = htons(0xffff);
1705 
1706 	if (lsc->lsc_optimistic)
1707 		pi->lpi_state = LACP_PARTNER_ADMIN_OPTIMISTIC;
1708 	else
1709 		pi->lpi_state = LACP_PARTNER_ADMIN_STRICT;
1710 
1711 	SET(lacpp->lp_actor.lpi_state, LACP_STATE_DEFAULTED);
1712 
1713 	if (oldpstate != pi->lpi_state) {
1714 		LACP_STATE_STR(oldpstate, buf, sizeof(buf));
1715 		LACP_DPRINTF((lsc, lacpp, "oldpstate %s\n", buf));
1716 
1717 		LACP_STATE_STR(pi->lpi_state, buf, sizeof(buf));
1718 		LACP_DPRINTF((lsc, lacpp, "newpstate %s\n", buf));
1719 	}
1720 
1721 	lacp_sm_ptx_update_timeout(lacpp, oldpstate);
1722 }
1723 
1724 static inline bool
lacp_port_is_synced(struct lacp_softc * lsc,struct lacp_port * lacpp,struct lacpdu_peerinfo * my_pi,struct lacpdu_peerinfo * peer_pi)1725 lacp_port_is_synced(struct lacp_softc *lsc, struct lacp_port *lacpp,
1726     struct lacpdu_peerinfo *my_pi, struct lacpdu_peerinfo *peer_pi)
1727 {
1728 	struct lacpdu_peerinfo actor;
1729 
1730 	if (!ISSET(peer_pi->lpi_state, LACP_STATE_ACTIVITY) &&
1731 	    (!ISSET(my_pi->lpi_state, LACP_STATE_ACTIVITY) ||
1732 	    !ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_ACTIVITY)))
1733 		return false;
1734 
1735 	if (!ISSET(peer_pi->lpi_state, LACP_STATE_AGGREGATION))
1736 		return false;
1737 
1738 	lacp_peerinfo_actor(lsc, lacpp, &actor);
1739 	if (lacp_compare_peerinfo(&actor, my_pi) != 0)
1740 		return false;
1741 
1742 	if (!LACP_STATE_EQ(actor.lpi_state, my_pi->lpi_state,
1743 	    LACP_STATE_AGGREGATION)) {
1744 		return false;
1745 	}
1746 
1747 	return true;
1748 }
1749 
1750 static void
lacp_sm_rx_record_peerinfo(struct lacp_softc * lsc,struct lacp_port * lacpp,struct lacpdu_peerinfo * my_pi,struct lacpdu_peerinfo * peer_pi)1751 lacp_sm_rx_record_peerinfo(struct lacp_softc *lsc, struct lacp_port *lacpp,
1752     struct lacpdu_peerinfo *my_pi, struct lacpdu_peerinfo *peer_pi)
1753 {
1754 	char buf[LACP_STATESTR_LEN] __LACPDEBUGUSED;
1755 	uint8_t oldpstate;
1756 	struct lacp_portinfo *pi;
1757 	struct lacp_aggregator_systemid *sid;
1758 
1759 	pi = &lacpp->lp_partner;
1760 	sid = &lacpp->lp_aggregator_sidbuf;
1761 
1762 	oldpstate = lacpp->lp_partner.lpi_state;
1763 
1764 	sid->sid_prio = peer_pi->lpi_system_prio;
1765 	sid->sid_key = peer_pi->lpi_key;
1766 	memcpy(sid->sid_mac, peer_pi->lpi_system_mac,
1767 	    sizeof(sid->sid_mac));
1768 
1769 	pi->lpi_portno = peer_pi->lpi_port_no;
1770 	pi->lpi_portprio = peer_pi->lpi_port_prio;
1771 	pi->lpi_state = peer_pi->lpi_state;
1772 
1773 	if (lacp_port_is_synced(lsc, lacpp, my_pi, peer_pi)) {
1774 		if (lsc->lsc_optimistic)
1775 			SET(lacpp->lp_partner.lpi_state, LACP_STATE_SYNC);
1776 	} else {
1777 		CLR(lacpp->lp_partner.lpi_state, LACP_STATE_SYNC);
1778 	}
1779 
1780 	CLR(lacpp->lp_actor.lpi_state, LACP_STATE_DEFAULTED);
1781 
1782 	if (oldpstate != lacpp->lp_partner.lpi_state) {
1783 		LACP_STATE_STR(oldpstate, buf, sizeof(buf));
1784 		LACP_DPRINTF((lsc, lacpp, "oldpstate %s\n", buf));
1785 
1786 		LACP_STATE_STR(lacpp->lp_partner.lpi_state,
1787 		    buf, sizeof(buf));
1788 		LACP_DPRINTF((lsc, lacpp, "newpstate %s\n", buf));
1789 	}
1790 
1791 	lacp_sm_ptx_update_timeout(lacpp, oldpstate);
1792 }
1793 
1794 static void
lacp_sm_rx_set_expired(struct lacp_port * lacpp)1795 lacp_sm_rx_set_expired(struct lacp_port *lacpp)
1796 {
1797 	uint8_t oldpstate;
1798 
1799 	oldpstate = lacpp->lp_partner.lpi_state;
1800 
1801 	CLR(lacpp->lp_partner.lpi_state, LACP_STATE_SYNC);
1802 	SET(lacpp->lp_partner.lpi_state, LACP_STATE_TIMEOUT);
1803 	LACP_TIMER_ARM(lacpp, LACP_TIMER_CURRENT_WHILE,
1804 	    LACP_SHORT_TIMEOUT_TIME);
1805 	SET(lacpp->lp_actor.lpi_state, LACP_STATE_EXPIRED);
1806 
1807 	lacp_sm_ptx_update_timeout(lacpp, oldpstate);
1808 }
1809 
1810 static void
lacp_sm_port_init(struct lacp_softc * lsc,struct lacp_port * lacpp,struct lagg_port * lp)1811 lacp_sm_port_init(struct lacp_softc *lsc, struct lacp_port *lacpp,
1812     struct lagg_port *lp)
1813 {
1814 
1815 	KASSERT(LACP_LOCKED(lsc));
1816 
1817 	lacpp->lp_laggport = lp;
1818 	lacpp->lp_actor.lpi_state = LACP_STATE_ACTIVITY;
1819 	lacpp->lp_actor.lpi_portno = htons(if_get_index(lp->lp_ifp));
1820 	lacpp->lp_actor.lpi_portprio = htons(LACP_PORT_PRIO);
1821 	lacpp->lp_partner.lpi_state = LACP_STATE_TIMEOUT;
1822 	lacpp->lp_aggregator = NULL;
1823 	lacpp->lp_marker_xid = 0;
1824 	lacpp->lp_mux_state = LACP_MUX_INIT;
1825 
1826 	lacp_set_mux(lsc, lacpp, LACP_MUX_DETACHED);
1827 	lacp_sm_rx_record_default(lsc, lacpp);
1828 }
1829 
1830 static void
lacp_port_disable(struct lacp_softc * lsc,struct lacp_port * lacpp)1831 lacp_port_disable(struct lacp_softc *lsc, struct lacp_port *lacpp)
1832 {
1833 
1834 	KASSERT(LACP_LOCKED(lsc));
1835 
1836 	if (ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_AGGREGATION))
1837 		LACP_DPRINTF((lsc, lacpp, "enable -> disable\n"));
1838 
1839 	lacp_set_mux(lsc, lacpp, LACP_MUX_DETACHED);
1840 	lacp_sm_rx_record_default(lsc, lacpp);
1841 	CLR(lacpp->lp_actor.lpi_state,
1842 	    LACP_STATE_AGGREGATION | LACP_STATE_EXPIRED);
1843 	CLR(lacpp->lp_partner.lpi_state, LACP_STATE_AGGREGATION);
1844 }
1845 
1846 static void
lacp_port_enable(struct lacp_softc * lsc __LACPDEBUGUSED,struct lacp_port * lacpp)1847 lacp_port_enable(struct lacp_softc *lsc __LACPDEBUGUSED,
1848     struct lacp_port *lacpp)
1849 {
1850 
1851 	KASSERT(LACP_LOCKED(lsc));
1852 
1853 	if (!ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_AGGREGATION))
1854 		LACP_DPRINTF((lsc, lacpp, "disable -> enable\n"));
1855 
1856 	SET(lacpp->lp_actor.lpi_state, LACP_STATE_AGGREGATION);
1857 	lacp_sm_rx_set_expired(lacpp);
1858 }
1859 
1860 static void
lacp_sm_rx_timer(struct lacp_softc * lsc,struct lacp_port * lacpp)1861 lacp_sm_rx_timer(struct lacp_softc *lsc, struct lacp_port *lacpp)
1862 {
1863 
1864 	KASSERT(LACP_LOCKED(lsc));
1865 
1866 	if (!ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_EXPIRED)) {
1867 		/* CURRENT -> EXPIRED */
1868 		LACP_DPRINTF((lsc, lacpp, "CURRENT -> EXPIRED\n"));
1869 		lacp_sm_rx_set_expired(lacpp);
1870 	} else {
1871 		LACP_DPRINTF((lsc, lacpp, "EXPIRED -> DEFAULTED\n"));
1872 		lacp_set_mux(lsc, lacpp, LACP_MUX_DETACHED);
1873 		lacp_sm_rx_record_default(lsc, lacpp);
1874 	}
1875 }
1876 
1877 static void
lacp_sm_ptx_timer(struct lacp_softc * lsc __unused,struct lacp_port * lacpp)1878 lacp_sm_ptx_timer(struct lacp_softc *lsc __unused, struct lacp_port *lacpp)
1879 {
1880 
1881 	KASSERT(LACP_LOCKED(lsc));
1882 	lacp_sm_assert_ntt(lacpp);
1883 }
1884 
1885 static void
lacp_sm_ptx_schedule(struct lacp_port * lacpp)1886 lacp_sm_ptx_schedule(struct lacp_port *lacpp)
1887 {
1888 	int timeout;
1889 
1890 	/* no periodic */
1891 	if (!ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_ACTIVITY) &&
1892 	    !ISSET(lacpp->lp_partner.lpi_state, LACP_STATE_ACTIVITY)) {
1893 		LACP_TIMER_DISARM(lacpp, LACP_TIMER_PERIODIC);
1894 		return;
1895 	}
1896 
1897 	if (LACP_TIMER_ISARMED(lacpp, LACP_TIMER_PERIODIC))
1898 		return;
1899 
1900 	timeout = ISSET(lacpp->lp_partner.lpi_state, LACP_STATE_TIMEOUT) ?
1901 		LACP_FAST_PERIODIC_TIME : LACP_SLOW_PERIODIC_TIME;
1902 
1903 	LACP_TIMER_ARM(lacpp, LACP_TIMER_PERIODIC, timeout);
1904 }
1905 
1906 static void
lacp_sm_ptx_update_timeout(struct lacp_port * lacpp,uint8_t oldpstate)1907 lacp_sm_ptx_update_timeout(struct lacp_port *lacpp, uint8_t oldpstate)
1908 {
1909 
1910 	if (LACP_STATE_EQ(oldpstate, lacpp->lp_partner.lpi_state,
1911 	    LACP_STATE_TIMEOUT))
1912 		return;
1913 
1914 	LACP_DPRINTF((NULL, lacpp, "partner timeout changed\n"));
1915 
1916 	LACP_TIMER_DISARM(lacpp, LACP_TIMER_PERIODIC);
1917 
1918 	/* if timeout has been shorted, assert NTT */
1919 	if (ISSET(lacpp->lp_partner.lpi_state, LACP_STATE_TIMEOUT))
1920 		lacp_sm_assert_ntt(lacpp);
1921 }
1922 
1923 static void
lacp_sm_mux_timer(struct lacp_softc * lsc __LACPDEBUGUSED,struct lacp_port * lacpp)1924 lacp_sm_mux_timer(struct lacp_softc *lsc __LACPDEBUGUSED,
1925     struct lacp_port *lacpp)
1926 {
1927 	char buf[LACP_SYSTEMIDSTR_LEN] __LACPDEBUGUSED;
1928 
1929 	KASSERT(LACP_LOCKED(lsc));
1930 	KASSERT(lacpp->lp_pending > 0);
1931 
1932 	LACP_AGGREGATOR_STR(lacpp->lp_aggregator, buf, sizeof(buf));
1933 	LACP_DPRINTF((lsc, lacpp, "aggregator %s, pending %d -> %d\n",
1934 	    buf, lacpp->lp_pending, lacpp->lp_pending -1));
1935 
1936 	lacpp->lp_pending--;
1937 }
1938 
1939 static void
lacp_sm_rx_update_selected(struct lacp_softc * lsc,struct lacp_port * lacpp,struct lacpdu_peerinfo * peer_pi)1940 lacp_sm_rx_update_selected(struct lacp_softc *lsc, struct lacp_port *lacpp,
1941     struct lacpdu_peerinfo *peer_pi)
1942 {
1943 	struct lacpdu_peerinfo partner;
1944 	char str0[LACP_SYSTEMIDSTR_LEN] __LACPDEBUGUSED;
1945 	char str1[LACP_SYSTEMIDSTR_LEN] __LACPDEBUGUSED;
1946 
1947 	if (lacpp->lp_aggregator == NULL)
1948 		return;
1949 
1950 	lacp_peerinfo_partner(lacpp, &partner);
1951 	if (lacp_compare_peerinfo(peer_pi, &partner) != 0) {
1952 		LACP_PEERINFO_IDSTR(&partner, str0, sizeof(str0));
1953 		LACP_PEERINFO_IDSTR(peer_pi, str1, sizeof(str1));
1954 		LACP_DPRINTF((lsc, lacpp,
1955 		    "different peerinfo, %s vs %s\n", str0, str1));
1956 		goto do_unselect;
1957 	}
1958 
1959 	if (!LACP_STATE_EQ(lacpp->lp_partner.lpi_state,
1960 	    peer_pi->lpi_state, LACP_STATE_AGGREGATION)) {
1961 		LACP_DPRINTF((lsc, lacpp,
1962 		    "STATE_AGGREGATION changed %d -> %d\n",
1963 		    ISSET(lacpp->lp_partner.lpi_state,
1964 		    LACP_STATE_AGGREGATION) != 0,
1965 		    ISSET(peer_pi->lpi_state, LACP_STATE_AGGREGATION) != 0));
1966 		goto do_unselect;
1967 	}
1968 
1969 	return;
1970 
1971 do_unselect:
1972 	lacpp->lp_selected = LACP_UNSELECTED;
1973 	/* lacpp->lp_aggregator will be released at lacp_set_mux() */
1974 }
1975 
1976 static void
lacp_sm_rx_update_ntt(struct lacp_softc * lsc,struct lacp_port * lacpp,struct lacpdu_peerinfo * my_pi)1977 lacp_sm_rx_update_ntt(struct lacp_softc *lsc, struct lacp_port *lacpp,
1978     struct lacpdu_peerinfo *my_pi)
1979 {
1980 	struct lacpdu_peerinfo actor;
1981 
1982 	lacp_peerinfo_actor(lsc, lacpp, &actor);
1983 
1984 	if (lacp_compare_peerinfo(&actor, my_pi) != 0 ||
1985 	    !LACP_STATE_EQ(lacpp->lp_actor.lpi_state, my_pi->lpi_state,
1986 	    LACP_STATE_ACTIVITY | LACP_STATE_SYNC | LACP_STATE_AGGREGATION)) {
1987 		if (ppsratecheck(&lacpp->lp_last_lacpdu, &lacpp->lp_lacpdu_sent,
1988 		    (LACP_SENDDU_PPS / LACP_FAST_PERIODIC_TIME)) == 0) {
1989 			LACP_DPRINTF((lsc, lacpp,
1990 			    "skip ntt due to rate limit"));
1991 		} else {
1992 			LACP_DPRINTF((lsc, lacpp, "assert ntt\n"));
1993 			lacp_sm_assert_ntt(lacpp);
1994 		}
1995 	}
1996 }
1997 
1998 static void
lacp_sm_rx(struct lacp_softc * lsc,struct lacp_port * lacpp,struct lacpdu_peerinfo * my_pi,struct lacpdu_peerinfo * peer_pi)1999 lacp_sm_rx(struct lacp_softc *lsc, struct lacp_port *lacpp,
2000     struct lacpdu_peerinfo *my_pi, struct lacpdu_peerinfo *peer_pi)
2001 {
2002 	int timeout;
2003 
2004 	KASSERT(LACP_LOCKED(lsc));
2005 
2006 	/* check LACP disabled first */
2007 	if (!ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_AGGREGATION))
2008 		return;
2009 
2010 	/* check loopback condition */
2011 	if (memcmp(lsc->lsc_system_mac, peer_pi->lpi_system_mac,
2012 	    LACP_MAC_LEN) == 0 &&
2013 	    lsc->lsc_system_prio == peer_pi->lpi_system_prio)
2014 		return;
2015 
2016 	lacp_sm_rx_update_selected(lsc, lacpp, peer_pi);
2017 	lacp_sm_rx_update_ntt(lsc, lacpp, my_pi);
2018 	lacp_sm_rx_record_peerinfo(lsc, lacpp, my_pi, peer_pi);
2019 
2020 	timeout = ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_TIMEOUT) ?
2021 	    LACP_SHORT_TIMEOUT_TIME : LACP_LONG_TIMEOUT_TIME;
2022 	LACP_TIMER_ARM(lacpp, LACP_TIMER_CURRENT_WHILE, timeout);
2023 
2024 	CLR(lacpp->lp_actor.lpi_state, LACP_STATE_EXPIRED);
2025 
2026 	/* kick transmit machine without timeout. */
2027 	lacp_sm_tx(lsc, lacpp);
2028 }
2029 
2030 static void
lacp_disable_collecting(struct lacp_port * lacpp)2031 lacp_disable_collecting(struct lacp_port *lacpp)
2032 {
2033 
2034 	LACP_DPRINTF((NULL, lacpp, "collecting disabled\n"));
2035 	CLR(lacpp->lp_actor.lpi_state, LACP_STATE_COLLECTING);
2036 	atomic_store_relaxed(&lacpp->lp_collector, false);
2037 }
2038 
2039 static void
lacp_enable_collecting(struct lacp_port * lacpp)2040 lacp_enable_collecting(struct lacp_port *lacpp)
2041 {
2042 	LACP_DPRINTF((NULL, lacpp, "collecting enabled\n"));
2043 	SET(lacpp->lp_actor.lpi_state, LACP_STATE_COLLECTING);
2044 	atomic_store_relaxed(&lacpp->lp_collector, true);
2045 }
2046 
2047 static void
lacp_update_portmap(struct lacp_softc * lsc)2048 lacp_update_portmap(struct lacp_softc *lsc)
2049 {
2050 	struct lagg_softc *sc;
2051 	struct lacp_aggregator *la;
2052 	struct lacp_portmap *pm_act, *pm_next;
2053 	struct lacp_port *lacpp;
2054 	size_t pmap, n;
2055 	u_int link;
2056 
2057 	KASSERT(LACP_LOCKED(lsc));
2058 
2059 	la = lsc->lsc_aggregator;
2060 
2061 	pmap = LACP_PORTMAP_ACTIVE(lsc);
2062 	pm_act = &lsc->lsc_portmaps[pmap];
2063 
2064 	pmap = LACP_PORTMAP_NEXT(lsc);
2065 	pm_next = &lsc->lsc_portmaps[pmap];
2066 
2067 	n = 0;
2068 	if (la != NULL) {
2069 		LIST_FOREACH(lacpp, &la->la_ports, lp_entry_la) {
2070 			if (!ISSET(lacpp->lp_actor.lpi_state,
2071 			    LACP_STATE_DISTRIBUTING)) {
2072 				continue;
2073 			}
2074 
2075 			pm_next->pm_ports[n] = lacpp->lp_laggport;
2076 			n++;
2077 
2078 			if (n >= LACP_MAX_PORTS)
2079 				break;
2080 		}
2081 	}
2082 	pm_next->pm_count = n;
2083 
2084 	atomic_store_release(&lsc->lsc_activemap, pmap);
2085 	pserialize_perform(lsc->lsc_psz);
2086 
2087 	LACP_DPRINTF((lsc, NULL, "portmap count updated (%zu -> %zu)\n",
2088 	    pm_act->pm_count, pm_next->pm_count));
2089 
2090 	link = lacp_portmap_linkstate(pm_next);
2091 	if (link != lacp_portmap_linkstate(pm_act)) {
2092 		sc = lsc->lsc_softc;
2093 		if_link_state_change(&sc->sc_if, link);
2094 	}
2095 
2096 	lagg_workq_add(lsc->lsc_workq,  &lsc->lsc_work_linkspeed);
2097 
2098 	/* cleanup */
2099 	pm_act->pm_count = 0;
2100 	memset(pm_act->pm_ports, 0, sizeof(pm_act->pm_ports));
2101 }
2102 
2103 static void
lacp_disable_distributing(struct lacp_softc * lsc,struct lacp_port * lacpp)2104 lacp_disable_distributing(struct lacp_softc *lsc, struct lacp_port *lacpp)
2105 {
2106 	struct lacp_portmap *pm;
2107 	bool do_update;
2108 	size_t act, i;
2109 	int s;
2110 
2111 	KASSERT(LACP_LOCKED(lsc));
2112 
2113 	if (ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_DISTRIBUTING)) {
2114 		LAGG_LOG(lsc->lsc_softc, LOG_INFO,
2115 		    "disable distributing on %s\n", LACP_PORT_XNAME(lacpp));
2116 		CLR(lacpp->lp_actor.lpi_state, LACP_STATE_DISTRIBUTING);
2117 	}
2118 
2119 	s = pserialize_read_enter();
2120 	act = LACP_PORTMAP_ACTIVE(lsc);
2121 	pm = &lsc->lsc_portmaps[act];
2122 
2123 	do_update = false;
2124 	for (i = 0; i < pm->pm_count; i++) {
2125 		if (pm->pm_ports[i] == lacpp->lp_laggport) {
2126 			do_update = true;
2127 			break;
2128 		}
2129 	}
2130 	pserialize_read_exit(s);
2131 
2132 	if (do_update)
2133 		lacp_update_portmap(lsc);
2134 }
2135 
2136 static void
lacp_enable_distributing(struct lacp_softc * lsc,struct lacp_port * lacpp)2137 lacp_enable_distributing(struct lacp_softc *lsc, struct lacp_port *lacpp)
2138 {
2139 
2140 	KASSERT(LACP_LOCKED(lsc));
2141 
2142 	KASSERT(lacp_isactive(lsc, lacpp));
2143 
2144 	LAGG_LOG(lsc->lsc_softc, LOG_INFO,
2145 	    "enable distributing on %s\n", LACP_PORT_XNAME(lacpp));
2146 	SET(lacpp->lp_actor.lpi_state, LACP_STATE_DISTRIBUTING);
2147 	lacp_suppress_distributing(lsc);
2148 	lacp_update_portmap(lsc);
2149 }
2150 
2151 static void
lacp_select_active_aggregator(struct lacp_softc * lsc)2152 lacp_select_active_aggregator(struct lacp_softc *lsc)
2153 {
2154 	struct lacp_aggregator *la, *best_la;
2155 	char str[LACP_SYSTEMIDSTR_LEN] __LACPDEBUGUSED;
2156 
2157 	KASSERT(LACP_LOCKED(lsc));
2158 
2159 	la = lsc->lsc_aggregator;
2160 	if (la != NULL && la->la_attached_port > 0) {
2161 		best_la = la;
2162 	} else {
2163 		best_la = NULL;
2164 	}
2165 
2166 	TAILQ_FOREACH(la, &lsc->lsc_aggregators, la_q) {
2167 		if (la->la_attached_port <= 0)
2168 			continue;
2169 
2170 		if (best_la == NULL ||
2171 		    LACP_SYS_PRI(la) < LACP_SYS_PRI(best_la))
2172 			best_la = la;
2173 	}
2174 
2175 	if (best_la != lsc->lsc_aggregator) {
2176 		LACP_DPRINTF((lsc, NULL, "active aggregator changed\n"));
2177 
2178 		if (lsc->lsc_aggregator != NULL) {
2179 			LACP_AGGREGATOR_STR(lsc->lsc_aggregator,
2180 			    str, sizeof(str));
2181 		} else {
2182 			snprintf(str, sizeof(str), "(null)");
2183 		}
2184 		LACP_DPRINTF((lsc, NULL, "old aggregator=%s\n", str));
2185 
2186 		if (best_la != NULL) {
2187 			LACP_AGGREGATOR_STR(best_la, str, sizeof(str));
2188 		} else {
2189 			snprintf(str, sizeof(str), "(null)");
2190 		}
2191 		LACP_DPRINTF((lsc, NULL, "new aggregator=%s\n", str));
2192 
2193 		lsc->lsc_aggregator = best_la;
2194 	}
2195 }
2196 
2197 static void
lacp_port_attached(struct lacp_softc * lsc,struct lacp_port * lacpp)2198 lacp_port_attached(struct lacp_softc *lsc, struct lacp_port *lacpp)
2199 {
2200 	struct lacp_aggregator *la;
2201 
2202 	KASSERT(LACP_LOCKED(lsc));
2203 
2204 	if (ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_SYNC))
2205 		return;
2206 
2207 	la = lacpp->lp_aggregator;
2208 	KASSERT(la != NULL);
2209 	KASSERT(la->la_attached_port >= 0);
2210 
2211 	SET(lacpp->lp_actor.lpi_state, LACP_STATE_SYNC);
2212 	la->la_attached_port++;
2213 	lacp_select_active_aggregator(lsc);
2214 }
2215 
2216 static void
lacp_port_detached(struct lacp_softc * lsc,struct lacp_port * lacpp)2217 lacp_port_detached(struct lacp_softc *lsc, struct lacp_port *lacpp)
2218 {
2219 	struct lacp_aggregator *la;
2220 
2221 	KASSERT(LACP_LOCKED(lsc));
2222 
2223 	if (!ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_SYNC))
2224 		return;
2225 
2226 	la = lacpp->lp_aggregator;
2227 	KASSERT(la != NULL);
2228 	KASSERT(la->la_attached_port > 0);
2229 
2230 	CLR(lacpp->lp_actor.lpi_state, LACP_STATE_SYNC);
2231 	la->la_attached_port--;
2232 	lacp_select_active_aggregator(lsc);
2233 }
2234 
2235 static int
lacp_set_mux(struct lacp_softc * lsc,struct lacp_port * lacpp,enum lacp_mux_state new_state)2236 lacp_set_mux(struct lacp_softc *lsc, struct lacp_port *lacpp,
2237     enum lacp_mux_state new_state)
2238 {
2239 	struct lagg_softc *sc;
2240 	struct ifnet *ifp;
2241 
2242 	KASSERT(LACP_LOCKED(lsc));
2243 
2244 	sc = lacpp->lp_laggport->lp_softc;
2245 	ifp = &sc->sc_if;
2246 
2247 	if (lacpp->lp_mux_state == new_state)
2248 		return -1;
2249 
2250 	switch (new_state) {
2251 	case LACP_MUX_DETACHED:
2252 		lacp_port_detached(lsc, lacpp);
2253 		lacp_disable_distributing(lsc, lacpp);
2254 		lacp_disable_collecting(lacpp);
2255 		lacp_sm_assert_ntt(lacpp);
2256 		/* cancel timer */
2257 		if (LACP_TIMER_ISARMED(lacpp, LACP_TIMER_WAIT_WHILE)) {
2258 			KASSERT(lacpp->lp_pending > 0);
2259 			lacpp->lp_pending--;
2260 			LACP_TIMER_DISARM(lacpp, LACP_TIMER_WAIT_WHILE);
2261 		}
2262 		lacp_unselect(lsc, lacpp);
2263 		break;
2264 	case LACP_MUX_WAITING:
2265 		LACP_TIMER_ARM(lacpp, LACP_TIMER_WAIT_WHILE,
2266 		    LACP_AGGREGATE_WAIT_TIME);
2267 		lacpp->lp_pending++;
2268 		break;
2269 	case LACP_MUX_STANDBY:
2270 #ifdef LACP_STANDBY_SYNCED
2271 		lacp_port_attached(lsc, lacpp);
2272 		lacp_disable_collecting(lacpp);
2273 		lacp_sm_assert_ntt(lacpp);
2274 #endif
2275 		break;
2276 	case LACP_MUX_ATTACHED:
2277 		lacp_port_attached(lsc, lacpp);
2278 		lacp_disable_collecting(lacpp);
2279 		lacp_sm_assert_ntt(lacpp);
2280 		break;
2281 	case LACP_MUX_COLLECTING:
2282 		lacp_enable_collecting(lacpp);
2283 		lacp_disable_distributing(lsc, lacpp);
2284 		lacp_sm_assert_ntt(lacpp);
2285 		break;
2286 	case LACP_MUX_DISTRIBUTING:
2287 		lacp_enable_distributing(lsc, lacpp);
2288 		break;
2289 	case LACP_MUX_INIT:
2290 	default:
2291 		panic("%s: unknown state", ifp->if_xname);
2292 	}
2293 
2294 	LACP_DPRINTF((lsc, lacpp, "mux_state %d -> %d\n",
2295 	    lacpp->lp_mux_state, new_state));
2296 
2297 	lacpp->lp_mux_state = new_state;
2298 	return 0;
2299 }
2300 
2301 static void
lacp_sm_mux(struct lacp_softc * lsc,struct lacp_port * lacpp)2302 lacp_sm_mux(struct lacp_softc *lsc, struct lacp_port *lacpp)
2303 {
2304 	struct lacp_aggregator *la __diagused;
2305 	enum lacp_mux_state  next_state;
2306 	enum lacp_selected selected;
2307 	bool p_sync, p_collecting;
2308 
2309 	p_sync = ISSET(lacpp->lp_partner.lpi_state, LACP_STATE_SYNC);
2310 	p_collecting = ISSET(lacpp->lp_partner.lpi_state,
2311 	    LACP_STATE_COLLECTING);
2312 
2313 	do {
2314 		next_state = lacpp->lp_mux_state;
2315 		la = lacpp->lp_aggregator;
2316 		selected = lacpp->lp_selected;
2317 		KASSERT(la != NULL ||
2318 		    lacpp->lp_mux_state == LACP_MUX_DETACHED);
2319 
2320 		switch (lacpp->lp_mux_state) {
2321 		case LACP_MUX_DETACHED:
2322 			if (selected != LACP_UNSELECTED)
2323 				next_state = LACP_MUX_WAITING;
2324 			break;
2325 		case LACP_MUX_WAITING:
2326 			KASSERTMSG((lacpp->lp_pending > 0 ||
2327 			    !LACP_TIMER_ISARMED(lacpp, LACP_TIMER_WAIT_WHILE)),
2328 			    "lp_pending=%d, timer=%d", lacpp->lp_pending,
2329 			    !LACP_TIMER_ISARMED(lacpp, LACP_TIMER_WAIT_WHILE));
2330 
2331 			if (selected == LACP_UNSELECTED) {
2332 				next_state = LACP_MUX_DETACHED;
2333 			} else if (lacpp->lp_pending == 0) {
2334 				if (selected == LACP_SELECTED) {
2335 					next_state = LACP_MUX_ATTACHED;
2336 				} else if (selected == LACP_STANDBY) {
2337 					next_state = LACP_MUX_STANDBY;
2338 				} else {
2339 					next_state = LACP_MUX_DETACHED;
2340 				}
2341 			}
2342 			break;
2343 		case LACP_MUX_STANDBY:
2344 			if (selected == LACP_SELECTED) {
2345 				next_state = LACP_MUX_ATTACHED;
2346 			} else if (selected != LACP_STANDBY) {
2347 				next_state = LACP_MUX_DETACHED;
2348 			}
2349 			break;
2350 		case LACP_MUX_ATTACHED:
2351 			if (selected != LACP_SELECTED) {
2352 				if (selected == LACP_STANDBY)
2353 					LAGG_LOG(lsc->lsc_softc, LOG_INFO,
2354 					    "detaching %s\n",
2355 					    LACP_PORT_XNAME(lacpp));
2356 				next_state = LACP_MUX_DETACHED;
2357 			} else if (lacp_isactive(lsc, lacpp) && p_sync) {
2358 				next_state = LACP_MUX_COLLECTING;
2359 			}
2360 			break;
2361 		case LACP_MUX_COLLECTING:
2362 			if (selected != LACP_SELECTED ||
2363 			    !lacp_isactive(lsc, lacpp)
2364 			    || !p_sync) {
2365 				next_state = LACP_MUX_ATTACHED;
2366 			} else if (p_collecting) {
2367 				next_state = LACP_MUX_DISTRIBUTING;
2368 			}
2369 			break;
2370 		case LACP_MUX_DISTRIBUTING:
2371 			if (selected != LACP_SELECTED ||
2372 			    !lacp_isactive(lsc, lacpp)
2373 			    || !p_sync || !p_collecting) {
2374 				next_state = LACP_MUX_COLLECTING;
2375 				LACP_DPRINTF((lsc, lacpp,
2376 				    "Interface stopped DISTRIBUTING,"
2377 				    " possible flapping\n"));
2378 			}
2379 			break;
2380 		case LACP_MUX_INIT:
2381 		default:
2382 			panic("%s: unknown state",
2383 			    lsc->lsc_softc->sc_if.if_xname);
2384 		}
2385 	} while (lacp_set_mux(lsc, lacpp, next_state) == 0);
2386 }
2387 
2388 static bool
lacp_aggregator_is_match(struct lacp_aggregator_systemid * a,struct lacp_aggregator_systemid * b)2389 lacp_aggregator_is_match(struct lacp_aggregator_systemid *a,
2390 struct lacp_aggregator_systemid *b)
2391 {
2392 
2393 	if (a->sid_prio != b->sid_prio)
2394 		return false;
2395 
2396 	if (a->sid_key != b->sid_key)
2397 		return false;
2398 
2399 	if (memcmp(a->sid_mac, b->sid_mac, sizeof(a->sid_mac)) != 0)
2400 		return false;
2401 
2402 	return true;
2403 }
2404 
2405 static void
lacp_selected_update(struct lacp_softc * lsc,struct lacp_aggregator * la)2406 lacp_selected_update(struct lacp_softc *lsc, struct lacp_aggregator *la)
2407 {
2408 	struct lacp_port *lacpp;
2409 	enum lacp_selected next_selected;
2410 	const char *msg;
2411 	size_t nselected;
2412 	uint64_t linkspeed;
2413 
2414 	KASSERT(LACP_LOCKED(lsc));
2415 
2416 	lacpp = LIST_FIRST(&la->la_ports);
2417 	if (lacpp == NULL)
2418 		return;
2419 
2420 	linkspeed = lacpp->lp_linkspeed;
2421 	nselected = 0;
2422 	LIST_FOREACH(lacpp, &la->la_ports, lp_entry_la) {
2423 		if (lacpp->lp_selected == LACP_UNSELECTED)
2424 			continue;
2425 
2426 		next_selected = LACP_SELECTED;
2427 		msg = " is selected";
2428 
2429 		if (nselected >= lsc->lsc_max_ports) {
2430 			next_selected = LACP_STANDBY;
2431 			msg = " is standby because of too many active ports";
2432 		}
2433 
2434 		if (!lsc->lsc_multi_linkspeed &&
2435 		    linkspeed != lacpp->lp_linkspeed) {
2436 			next_selected = LACP_STANDBY;
2437 			msg = " is standby because of link speed mismatch";
2438 		}
2439 
2440 		if (lacpp->lp_selected != next_selected) {
2441 			lacpp->lp_selected = next_selected;
2442 			LAGG_LOG(lsc->lsc_softc, LOG_INFO,
2443 			    "%s%s\n", LACP_PORT_XNAME(lacpp), msg);
2444 		}
2445 
2446 		if (lacpp->lp_selected == LACP_SELECTED)
2447 			nselected++;
2448 	}
2449 }
2450 
2451 static void
lacp_select(struct lacp_softc * lsc,struct lacp_port * lacpp)2452 lacp_select(struct lacp_softc *lsc, struct lacp_port *lacpp)
2453 {
2454 	struct lacp_aggregator *la;
2455 	struct lacp_aggregator_systemid *sid;
2456 	struct lacp_port *lacpp0;
2457 	char buf[LACP_SYSTEMIDSTR_LEN] __LACPDEBUGUSED;
2458 
2459 	if (lacpp->lp_aggregator != NULL)
2460 		return;
2461 
2462 	/* If we haven't heard from our peer, skip this step. */
2463 	if (ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_DEFAULTED))
2464 		return
2465 
2466 	KASSERT(!LACP_TIMER_ISARMED(lacpp, LACP_TIMER_WAIT_WHILE));
2467 
2468 	sid = &lacpp->lp_aggregator_sidbuf;
2469 
2470 	TAILQ_FOREACH(la, &lsc->lsc_aggregators, la_q) {
2471 		if (lacp_aggregator_is_match(&la->la_sid, sid))
2472 			break;
2473 	}
2474 
2475 	if (la == NULL) {
2476 		la = kmem_zalloc(sizeof(*la), KM_NOSLEEP);
2477 		if (la == NULL) {
2478 			LACP_DPRINTF((lsc, lacpp,
2479 			    "couldn't allocate aggregator\n"));
2480 			/* will retry the next tick. */
2481 			return;
2482 		}
2483 		LIST_INIT(&la->la_ports);
2484 
2485 		la->la_sid = *sid;
2486 		TAILQ_INSERT_TAIL(&lsc->lsc_aggregators, la, la_q);
2487 		LACP_DPRINTF((lsc, lacpp, "a new aggregator created\n"));
2488 	} else {
2489 		LACP_DPRINTF((lsc, lacpp, "aggregator found\n"));
2490 	}
2491 
2492 	KASSERT(la != NULL);
2493 	LACP_AGGREGATOR_STR(la, buf, sizeof(buf));
2494 	LACP_DPRINTF((lsc, lacpp, "aggregator lagid=%s\n", buf));
2495 
2496 	lacpp->lp_aggregator = la;
2497 	lacpp->lp_selected = LACP_READY;
2498 
2499 	LIST_FOREACH(lacpp0, &la->la_ports, lp_entry_la) {
2500 		if (lacp_port_priority_max(lacpp0, lacpp) == lacpp) {
2501 			LIST_INSERT_BEFORE(lacpp0, lacpp, lp_entry_la);
2502 			break;
2503 		}
2504 
2505 		if (LIST_NEXT(lacpp0, lp_entry_la) == NULL) {
2506 			LIST_INSERT_AFTER(lacpp0, lacpp, lp_entry_la);
2507 			break;
2508 		}
2509 	}
2510 
2511 	if (lacpp0 == NULL)
2512 		LIST_INSERT_HEAD(&la->la_ports, lacpp, lp_entry_la);
2513 
2514 	lacp_selected_update(lsc, la);
2515 }
2516 
2517 static void
lacp_unselect(struct lacp_softc * lsc,struct lacp_port * lacpp)2518 lacp_unselect(struct lacp_softc *lsc, struct lacp_port *lacpp)
2519 {
2520 	struct lacp_aggregator *la;
2521 	char buf[LACP_SYSTEMIDSTR_LEN] __LACPDEBUGUSED;
2522 	bool remove_actaggr;
2523 
2524 	KASSERT(LACP_LOCKED(lsc));
2525 	KASSERT(!LACP_TIMER_ISARMED(lacpp, LACP_TIMER_WAIT_WHILE));
2526 
2527 	la = lacpp->lp_aggregator;
2528 	lacpp->lp_selected = LACP_UNSELECTED;
2529 
2530 	if (la == NULL)
2531 		return;
2532 
2533 	KASSERT(!LIST_EMPTY(&la->la_ports));
2534 
2535 	LACP_AGGREGATOR_STR(la, buf, sizeof(buf));
2536 	LACP_DPRINTF((lsc, lacpp, "unselect aggregator lagid=%s\n", buf));
2537 
2538 	LIST_REMOVE(lacpp, lp_entry_la);
2539 	lacpp->lp_aggregator = NULL;
2540 
2541 	if (LIST_EMPTY(&la->la_ports)) {
2542 		remove_actaggr = false;
2543 
2544 		if (la == lsc->lsc_aggregator) {
2545 			LACP_DPRINTF((lsc, NULL, "remove active aggregator\n"));
2546 			lsc->lsc_aggregator = NULL;
2547 			remove_actaggr = true;
2548 		}
2549 
2550 		TAILQ_REMOVE(&lsc->lsc_aggregators, la, la_q);
2551 		kmem_free(la, sizeof(*la));
2552 
2553 		if (remove_actaggr)
2554 			lacp_select_active_aggregator(lsc);
2555 	} else {
2556 		lacp_selected_update(lsc, la);
2557 	}
2558 }
2559 
2560 static void
lacp_suppress_distributing(struct lacp_softc * lsc)2561 lacp_suppress_distributing(struct lacp_softc *lsc)
2562 {
2563 	struct lacp_aggregator *la;
2564 	struct lacp_port *lacpp;
2565 	bool marker_scheduled;
2566 
2567 	KASSERT(LACP_LOCKED(lsc));
2568 
2569 	la = lsc->lsc_aggregator;
2570 	marker_scheduled = false;
2571 
2572 	LIST_FOREACH(lacpp, &la->la_ports, lp_entry_la) {
2573 		if (ISSET(lacpp->lp_actor.lpi_state,
2574 		    LACP_STATE_DISTRIBUTING)) {
2575 			lagg_workq_add(lsc->lsc_workq,
2576 			    &lacpp->lp_work_marker);
2577 			marker_scheduled = true;
2578 		}
2579 	}
2580 
2581 	lsc->lsc_suppress_distributing = marker_scheduled;
2582 	LACP_PTIMER_ARM(lsc, LACP_PTIMER_DISTRIBUTING,
2583 	    LACP_TRANSIT_DELAY);
2584 }
2585 
2586 static void
lacp_distributing_timer(struct lacp_softc * lsc)2587 lacp_distributing_timer(struct lacp_softc *lsc)
2588 {
2589 
2590 	KASSERT(LACP_LOCKED(lsc));
2591 
2592 	if (lsc->lsc_suppress_distributing) {
2593 		LACP_DPRINTF((lsc, NULL,
2594 		    "disable suppress distributing\n"));
2595 		lsc->lsc_suppress_distributing = false;
2596 	}
2597 }
2598 
2599 static struct mbuf *
lacp_markerdu_mbuf(struct lacp_softc * lsc,struct lacp_port * lacpp)2600 lacp_markerdu_mbuf(struct lacp_softc *lsc, struct lacp_port *lacpp)
2601 {
2602 	struct ifnet *ifp_port;
2603 	struct mbuf *m;
2604 	struct markerdu *mdu;
2605 	struct markerdu_info *mi;
2606 
2607 	KASSERT(LACP_LOCKED(lsc));
2608 
2609 	ifp_port = lacpp->lp_laggport->lp_ifp;
2610 
2611 	MGETHDR(m, M_DONTWAIT, MT_DATA);
2612 	if (m == NULL) {
2613 		lsc->lsc_mgethdr_failed.ev_count++;
2614 		return NULL;
2615 	}
2616 
2617 	m->m_pkthdr.len = m->m_len = sizeof(*mdu);
2618 	m_reset_rcvif(m);
2619 
2620 	mdu = mtod(m, struct markerdu *);
2621 
2622 	memset(mdu, 0, sizeof(*mdu));
2623 
2624 	m->m_flags |= M_MCAST;
2625 	memcpy(mdu->mdu_eh.ether_dhost, ethermulticastaddr_slowprotocols,
2626 	    ETHER_ADDR_LEN);
2627 	memcpy(mdu->mdu_eh.ether_shost, CLLADDR(ifp_port->if_sadl),
2628 	    ETHER_ADDR_LEN);
2629 	mdu->mdu_eh.ether_type = ntohs(ETHERTYPE_SLOWPROTOCOLS);
2630 	mdu->mdu_sph.sph_subtype = SLOWPROTOCOLS_SUBTYPE_MARKER;
2631 	mdu->mdu_sph.sph_version = 1;
2632 
2633 	mi = &mdu->mdu_info;
2634 	tlv_set(&mdu->mdu_tlv_info, MARKER_TYPE_INFO,
2635 	    sizeof(*mi));
2636 	mi->mi_rq_port = lacpp->lp_actor.lpi_portno;
2637 	mi->mi_rq_xid = htonl(lacpp->lp_marker_xid);
2638 	memcpy(mi->mi_rq_system, lsc->lsc_system_mac, LACP_MAC_LEN);
2639 
2640 	mdu->mdu_tlv_term.tlv_type = MARKER_TYPE_TERMINATE;
2641 	mdu->mdu_tlv_term.tlv_length = 0;
2642 
2643 	return m;
2644 }
2645 
2646 static void
lacp_marker_work(struct lagg_work * lw,void * xlsc)2647 lacp_marker_work(struct lagg_work *lw, void *xlsc)
2648 {
2649 	struct lacp_softc *lsc;
2650 	struct lacp_port *lacpp;
2651 	struct lagg_port *lp;
2652 	struct markerdu *mdu;
2653 	struct mbuf *m;
2654 	struct psref psref;
2655 	int bound;
2656 
2657 	lsc = xlsc;
2658 	lacpp = container_of(lw, struct lacp_port, lp_work_marker);
2659 
2660 	LACP_LOCK(lsc);
2661 	lacpp->lp_marker_xid++;
2662 	m = lacp_markerdu_mbuf(lsc, lacpp);
2663 	if (m == NULL) {
2664 		LACP_UNLOCK(lsc);
2665 		return;
2666 	}
2667 	SET(lacpp->lp_flags, LACP_PORT_MARK);
2668 	lp = lacpp->lp_laggport;
2669 	bound = curlwp_bind();
2670 	lagg_port_getref(lp, &psref);
2671 	LACP_UNLOCK(lsc);
2672 
2673 	if (LACP_ISDUMPING(lsc)) {
2674 		lacp_dprintf(lsc, lacpp, "markerdu transmit\n");
2675 		mdu = mtod(m, struct markerdu *);
2676 		lacp_dump_markertlv(&mdu->mdu_info, NULL);
2677 	}
2678 
2679 	lagg_port_xmit(lp, m);
2680 	lagg_port_putref(lp, &psref);
2681 	curlwp_bindx(bound);
2682 }
2683 
2684 static void
lacp_dump_lacpdutlv(const struct lacpdu_peerinfo * pi_actor,const struct lacpdu_peerinfo * pi_partner,const struct lacpdu_collectorinfo * lci)2685 lacp_dump_lacpdutlv(const struct lacpdu_peerinfo *pi_actor,
2686     const struct lacpdu_peerinfo *pi_partner,
2687     const struct lacpdu_collectorinfo *lci)
2688 {
2689 	char str[LACP_STATESTR_LEN];
2690 
2691 	if (pi_actor != NULL) {
2692 		lacp_peerinfo_idstr(pi_actor, str, sizeof(str));
2693 		printf("actor=%s\n", str);
2694 		lacp_state_str(pi_actor->lpi_state,
2695 		    str, sizeof(str));
2696 		printf("actor.state=%s portno=%d portprio=0x%04x\n",
2697 		    str,
2698 		    ntohs(pi_actor->lpi_port_no),
2699 		    ntohs(pi_actor->lpi_port_prio));
2700 	} else {
2701 		printf("no actor info\n");
2702 	}
2703 
2704 	if (pi_partner != NULL) {
2705 		lacp_peerinfo_idstr(pi_partner, str, sizeof(str));
2706 		printf("partner=%s\n", str);
2707 		lacp_state_str(pi_partner->lpi_state,
2708 		    str, sizeof(str));
2709 		printf("partner.state=%s portno=%d portprio=0x%04x\n",
2710 		    str,
2711 		    ntohs(pi_partner->lpi_port_no),
2712 		    ntohs(pi_partner->lpi_port_prio));
2713 	} else {
2714 		printf("no partner info\n");
2715 	}
2716 
2717 	if (lci != NULL) {
2718 		printf("maxdelay=%d\n", ntohs(lci->lci_maxdelay));
2719 	} else {
2720 		printf("no collector info\n");
2721 	}
2722 }
2723 
2724 static void
lacp_dump_markertlv(const struct markerdu_info * mi_info,const struct markerdu_info * mi_res)2725 lacp_dump_markertlv(const struct markerdu_info *mi_info,
2726     const struct markerdu_info *mi_res)
2727 {
2728 
2729 	if (mi_info != NULL) {
2730 		printf("marker info: port=%d, sys=%s, id=%u\n",
2731 		    ntohs(mi_info->mi_rq_port),
2732 		    ether_sprintf(mi_info->mi_rq_system),
2733 		    ntohl(mi_info->mi_rq_xid));
2734 	}
2735 
2736 	if (mi_res != NULL) {
2737 		printf("marker resp: port=%d, sys=%s, id=%u\n",
2738 		    ntohs(mi_res->mi_rq_port),
2739 		    ether_sprintf(mi_res->mi_rq_system),
2740 		    ntohl(mi_res->mi_rq_xid));
2741 	}
2742 }
2743 
2744 /*
2745  * lacp_linkstate:
2746  *   callback on link state changed.
2747  *   enable, disable or reset LACP processing on the physical port.
2748  */
2749 
2750 static void
lacp_linkstate(struct lagg_proto_softc * xlsc,struct lagg_port * lp)2751 lacp_linkstate(struct lagg_proto_softc *xlsc, struct lagg_port *lp)
2752 {
2753 
2754 	IFNET_ASSERT_UNLOCKED(lp->lp_ifp);
2755 
2756 	IFNET_LOCK(lp->lp_ifp);
2757 	lacp_linkstate_ifnet_locked(xlsc, lp);
2758 	IFNET_UNLOCK(lp->lp_ifp);
2759 }
2760 
2761 static void
lacp_linkspeed_work(struct lagg_work * lw __unused,void * xlsc)2762 lacp_linkspeed_work(struct lagg_work *lw __unused, void *xlsc)
2763 {
2764 	struct lacp_softc *lsc = (struct lacp_softc *)xlsc;
2765 	struct lagg_softc *sc = lsc->lsc_softc;
2766 	struct lacp_portmap *pm;
2767 	struct lagg_port *lp;
2768 	struct lacp_port *lacpp;
2769 	uint64_t linkspeed;
2770 	size_t act, i;
2771 
2772 	linkspeed = 0;
2773 
2774 	LACP_LOCK(lsc);
2775 	act = LACP_PORTMAP_ACTIVE(lsc);
2776 	pm = &lsc->lsc_portmaps[act];
2777 	for (i = 0; i < pm->pm_count; i++) {
2778 		lp = pm->pm_ports[i];
2779 		lacpp = lp->lp_proto_ctx;
2780 		linkspeed = MAX(linkspeed, lacpp->lp_linkspeed);
2781 	}
2782 	LACP_UNLOCK(lsc);
2783 
2784 	LAGG_LOCK(sc);
2785 	lagg_set_linkspeed(sc, linkspeed);
2786 	LAGG_UNLOCK(sc);
2787 }
2788