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