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