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