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