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