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